diff --git a/api/poktroll/supplier/params.pulsar.go b/api/poktroll/supplier/params.pulsar.go index da1387d1d..bb3c96973 100644 --- a/api/poktroll/supplier/params.pulsar.go +++ b/api/poktroll/supplier/params.pulsar.go @@ -3,6 +3,7 @@ package supplier import ( _ "cosmossdk.io/api/amino" + v1beta1 "cosmossdk.io/api/cosmos/base/v1beta1" fmt "fmt" runtime "github.com/cosmos/cosmos-proto/runtime" _ "github.com/cosmos/gogoproto/gogoproto" @@ -15,12 +16,14 @@ import ( ) var ( - md_Params protoreflect.MessageDescriptor + md_Params protoreflect.MessageDescriptor + fd_Params_min_stake protoreflect.FieldDescriptor ) func init() { file_poktroll_supplier_params_proto_init() md_Params = File_poktroll_supplier_params_proto.Messages().ByName("Params") + fd_Params_min_stake = md_Params.Fields().ByName("min_stake") } var _ protoreflect.Message = (*fastReflection_Params)(nil) @@ -88,6 +91,12 @@ func (x *fastReflection_Params) Interface() protoreflect.ProtoMessage { // While iterating, mutating operations may only be performed // on the current field descriptor. func (x *fastReflection_Params) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.MinStake != nil { + value := protoreflect.ValueOfMessage(x.MinStake.ProtoReflect()) + if !f(fd_Params_min_stake, value) { + return + } + } } // Has reports whether a field is populated. @@ -103,6 +112,8 @@ func (x *fastReflection_Params) Range(f func(protoreflect.FieldDescriptor, proto // a repeated field is populated if it is non-empty. func (x *fastReflection_Params) Has(fd protoreflect.FieldDescriptor) bool { switch fd.FullName() { + case "poktroll.supplier.Params.min_stake": + return x.MinStake != nil default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.supplier.Params")) @@ -119,6 +130,8 @@ func (x *fastReflection_Params) Has(fd protoreflect.FieldDescriptor) bool { // Clear is a mutating operation and unsafe for concurrent use. func (x *fastReflection_Params) Clear(fd protoreflect.FieldDescriptor) { switch fd.FullName() { + case "poktroll.supplier.Params.min_stake": + x.MinStake = nil default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.supplier.Params")) @@ -135,6 +148,9 @@ func (x *fastReflection_Params) Clear(fd protoreflect.FieldDescriptor) { // of the value; to obtain a mutable reference, use Mutable. func (x *fastReflection_Params) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { switch descriptor.FullName() { + case "poktroll.supplier.Params.min_stake": + value := x.MinStake + return protoreflect.ValueOfMessage(value.ProtoReflect()) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.supplier.Params")) @@ -155,6 +171,8 @@ func (x *fastReflection_Params) Get(descriptor protoreflect.FieldDescriptor) pro // Set is a mutating operation and unsafe for concurrent use. func (x *fastReflection_Params) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { switch fd.FullName() { + case "poktroll.supplier.Params.min_stake": + x.MinStake = value.Message().Interface().(*v1beta1.Coin) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.supplier.Params")) @@ -175,6 +193,11 @@ func (x *fastReflection_Params) Set(fd protoreflect.FieldDescriptor, value proto // Mutable is a mutating operation and unsafe for concurrent use. func (x *fastReflection_Params) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { switch fd.FullName() { + case "poktroll.supplier.Params.min_stake": + if x.MinStake == nil { + x.MinStake = new(v1beta1.Coin) + } + return protoreflect.ValueOfMessage(x.MinStake.ProtoReflect()) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.supplier.Params")) @@ -188,6 +211,9 @@ func (x *fastReflection_Params) Mutable(fd protoreflect.FieldDescriptor) protore // For lists, maps, and messages, this returns a new, empty, mutable value. func (x *fastReflection_Params) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { switch fd.FullName() { + case "poktroll.supplier.Params.min_stake": + m := new(v1beta1.Coin) + return protoreflect.ValueOfMessage(m.ProtoReflect()) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.supplier.Params")) @@ -257,6 +283,10 @@ func (x *fastReflection_Params) ProtoMethods() *protoiface.Methods { var n int var l int _ = l + if x.MinStake != nil { + l = options.Size(x.MinStake) + n += 1 + l + runtime.Sov(uint64(l)) + } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -286,6 +316,20 @@ func (x *fastReflection_Params) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } + if x.MinStake != nil { + encoded, err := options.Marshal(x.MinStake) + if err != nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) + i-- + dAtA[i] = 0xa + } if input.Buf != nil { input.Buf = append(input.Buf, dAtA...) } else { @@ -335,6 +379,42 @@ func (x *fastReflection_Params) ProtoMethods() *protoiface.Methods { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field MinStake", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if x.MinStake == nil { + x.MinStake = &v1beta1.Coin{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.MinStake); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -388,6 +468,10 @@ type Params struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + // min_stake is the minimum amount of uPOKT that a supplier must stake to be + // included in network sessions and remain staked. + MinStake *v1beta1.Coin `protobuf:"bytes,1,opt,name=min_stake,json=minStake,proto3" json:"min_stake,omitempty"` } func (x *Params) Reset() { @@ -410,6 +494,13 @@ func (*Params) Descriptor() ([]byte, []int) { return file_poktroll_supplier_params_proto_rawDescGZIP(), []int{0} } +func (x *Params) GetMinStake() *v1beta1.Coin { + if x != nil { + return x.MinStake + } + return nil +} + var File_poktroll_supplier_params_proto protoreflect.FileDescriptor var file_poktroll_supplier_params_proto_rawDesc = []byte{ @@ -418,22 +509,30 @@ var file_poktroll_supplier_params_proto_rawDesc = []byte{ 0x12, 0x11, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x1a, 0x11, 0x61, 0x6d, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x6d, 0x69, 0x6e, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x14, 0x67, 0x6f, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x67, 0x6f, 0x67, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x2d, 0x0a, 0x06, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3a, 0x23, 0xe8, 0xa0, 0x1f, 0x01, 0x8a, 0xe7, 0xb0, 0x2a, - 0x1a, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x78, 0x2f, 0x73, 0x75, 0x70, 0x70, - 0x6c, 0x69, 0x65, 0x72, 0x2f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0xb1, 0x01, 0xd8, 0xe2, - 0x1e, 0x01, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, - 0x2e, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x42, 0x0b, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x22, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, - 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6f, 0x6b, 0x74, 0x72, - 0x6f, 0x6c, 0x6c, 0x2f, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0xa2, 0x02, 0x03, 0x50, - 0x53, 0x58, 0xaa, 0x02, 0x11, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x53, 0x75, - 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0xca, 0x02, 0x11, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, - 0x6c, 0x5c, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0xe2, 0x02, 0x1d, 0x50, 0x6f, 0x6b, - 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x5c, 0x47, - 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x12, 0x50, 0x6f, 0x6b, - 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x3a, 0x3a, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x2f, 0x67, 0x6f, 0x67, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, + 0x31, 0x2f, 0x63, 0x6f, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x88, 0x01, 0x0a, + 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x59, 0x0a, 0x09, 0x6d, 0x69, 0x6e, 0x5f, 0x73, + 0x74, 0x61, 0x6b, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x21, 0xea, 0xde, 0x1f, 0x09, 0x6d, 0x69, 0x6e, 0x5f, 0x73, + 0x74, 0x61, 0x6b, 0x65, 0xf2, 0xde, 0x1f, 0x10, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x6d, 0x69, + 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x22, 0x52, 0x08, 0x6d, 0x69, 0x6e, 0x53, 0x74, 0x61, + 0x6b, 0x65, 0x3a, 0x23, 0xe8, 0xa0, 0x1f, 0x01, 0x8a, 0xe7, 0xb0, 0x2a, 0x1a, 0x70, 0x6f, 0x6b, + 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x78, 0x2f, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, + 0x2f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0xb1, 0x01, 0xd8, 0xe2, 0x1e, 0x01, 0x0a, 0x15, + 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x73, 0x75, 0x70, + 0x70, 0x6c, 0x69, 0x65, 0x72, 0x42, 0x0b, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x22, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, + 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, + 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0xa2, 0x02, 0x03, 0x50, 0x53, 0x58, 0xaa, 0x02, + 0x11, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x69, + 0x65, 0x72, 0xca, 0x02, 0x11, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x53, 0x75, + 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0xe2, 0x02, 0x1d, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, + 0x6c, 0x5c, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x12, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, + 0x6c, 0x3a, 0x3a, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -450,14 +549,16 @@ func file_poktroll_supplier_params_proto_rawDescGZIP() []byte { var file_poktroll_supplier_params_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_poktroll_supplier_params_proto_goTypes = []interface{}{ - (*Params)(nil), // 0: poktroll.supplier.Params + (*Params)(nil), // 0: poktroll.supplier.Params + (*v1beta1.Coin)(nil), // 1: cosmos.base.v1beta1.Coin } var file_poktroll_supplier_params_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name + 1, // 0: poktroll.supplier.Params.min_stake:type_name -> cosmos.base.v1beta1.Coin + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name } func init() { file_poktroll_supplier_params_proto_init() } diff --git a/config.yml b/config.yml index 57db72f1a..5ce114e81 100644 --- a/config.yml +++ b/config.yml @@ -193,6 +193,11 @@ genesis: amount: "100000068" # ~100 POKT denom: upokt supplier: + params: + # TODO_MAINNET: Determine realistic amount for minimum gateway stake amount. + min_stake: + amount: "1000000" # 1 POKT + denom: upokt supplierList: - owner_address: pokt19a3t4yunp0dlpfjrp7qwnzwlrzd5fzs2gjaaaj operator_address: pokt19a3t4yunp0dlpfjrp7qwnzwlrzd5fzs2gjaaaj diff --git a/makefiles/params.mk b/makefiles/params.mk index 17faca295..e2f736f10 100644 --- a/makefiles/params.mk +++ b/makefiles/params.mk @@ -111,7 +111,7 @@ params_get_gateway: ## Get the gateway module params poktrolld query gateway params --node $(POCKET_NODE) .PHONY: params_update_gateway_all -params_update_gateway_all: ## Update the session module params +params_update_gateway_all: ## Update the gateway module params poktrolld tx authz exec ./tools/scripts/params/gateway_all.json $(PARAM_FLAGS) .PHONY: params_update_gateway_min_stake @@ -135,6 +135,19 @@ params_update_application_max_delegated_gateways: ## Update the application modu params_update_application_min_stake: ## Update the application module min_stake param poktrolld tx authz exec ./tools/scripts/params/application_min_stake.json $(PARAM_FLAGS) +### Supplier Module Params ### +.PHONY: params_get_supplier +params_get_supplier: ## Get the supplier module params + poktrolld query supplier params --node $(POCKET_NODE) + +.PHONY: params_update_supplier_all +params_update_supplier_all: ## Update the supplier module params + poktrolld tx authz exec ./tools/scripts/params/supplier_all.json $(PARAM_FLAGS) + +.PHONY: params_update_supplier_min_stake +params_update_supplier_min_stake: ## Update the supplier module min_stake param + poktrolld tx authz exec ./tools/scripts/params/supplier_min_stake.json $(PARAM_FLAGS) + .PHONY: params_query_all params_query_all: check_jq ## Query the params from all available modules @for module in $(MODULES); do \ diff --git a/proto/poktroll/supplier/params.proto b/proto/poktroll/supplier/params.proto index ea532e61c..d4e8c77ec 100644 --- a/proto/poktroll/supplier/params.proto +++ b/proto/poktroll/supplier/params.proto @@ -6,9 +6,14 @@ option (gogoproto.stable_marshaler_all) = true; import "amino/amino.proto"; import "gogoproto/gogo.proto"; +import "cosmos/base/v1beta1/coin.proto"; // Params defines the parameters for the module. message Params { option (amino.name) = "poktroll/x/supplier/Params"; option (gogoproto.equal) = true; + + // min_stake is the minimum amount of uPOKT that a supplier must stake to be + // included in network sessions and remain staked. + cosmos.base.v1beta1.Coin min_stake = 1 [(gogoproto.jsontag) = "min_stake", (gogoproto.moretags) = "yaml:\"min_stake\""]; } diff --git a/testutil/integration/suites/param_configs.go b/testutil/integration/suites/param_configs.go index 740a7693d..1c1a9ac4f 100644 --- a/testutil/integration/suites/param_configs.go +++ b/testutil/integration/suites/param_configs.go @@ -183,7 +183,12 @@ var ( QueryParamsRequest: suppliertypes.QueryParamsRequest{}, QueryParamsResponse: suppliertypes.QueryParamsResponse{}, }, - ValidParams: suppliertypes.Params{}, + ValidParams: suppliertypes.Params{ + MinStake: &ValidActorMinStake, + }, + ParamTypes: map[ParamType]any{ + ParamTypeCoin: suppliertypes.MsgUpdateParam_AsCoin{}, + }, DefaultParams: suppliertypes.DefaultParams(), NewParamClientFn: suppliertypes.NewQueryClient, } diff --git a/tools/scripts/params/supplier_all.json b/tools/scripts/params/supplier_all.json new file mode 100644 index 000000000..cded3172f --- /dev/null +++ b/tools/scripts/params/supplier_all.json @@ -0,0 +1,16 @@ +{ + "body": { + "messages": [ + { + "@type": "/poktroll.supplier.MsgUpdateParams", + "authority": "pokt10d07y265gmmuvt4z0w9aw880jnsr700j8yv32t", + "params": { + "min_stake": { + "amount": "1000000", + "denom": "upokt" + } + } + } + ] + } +} \ No newline at end of file diff --git a/tools/scripts/params/supplier_min_stake.json b/tools/scripts/params/supplier_min_stake.json new file mode 100644 index 000000000..fa96d860c --- /dev/null +++ b/tools/scripts/params/supplier_min_stake.json @@ -0,0 +1,15 @@ +{ + "body": { + "messages": [ + { + "@type": "/poktroll.supplier.MsgUpdateParam", + "authority": "pokt10d07y265gmmuvt4z0w9aw880jnsr700j8yv32t", + "name": "min_stake", + "as_coin": { + "amount": "1000000", + "denom": "upokt" + } + } + ] + } +} diff --git a/x/supplier/keeper/msg_server_stake_supplier.go b/x/supplier/keeper/msg_server_stake_supplier.go index d3478cab7..f750b99ff 100644 --- a/x/supplier/keeper/msg_server_stake_supplier.go +++ b/x/supplier/keeper/msg_server_stake_supplier.go @@ -5,6 +5,8 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" "github.com/pokt-network/poktroll/telemetry" "github.com/pokt-network/poktroll/x/shared" @@ -25,15 +27,18 @@ func (k msgServer) StakeSupplier(ctx context.Context, msg *types.MsgStakeSupplie // ValidateBasic also validates that the msg signer is the owner or operator of the supplier if err := msg.ValidateBasic(); err != nil { - logger.Error(fmt.Sprintf("invalid MsgStakeSupplier: %v", msg)) - return nil, err + logger.Info(fmt.Sprintf("invalid MsgStakeSupplier: %v", msg)) + return nil, status.Error(codes.InvalidArgument, err.Error()) } // Check if the services the supplier is staking for exist for _, serviceConfig := range msg.Services { if _, serviceFound := k.serviceKeeper.GetService(ctx, serviceConfig.ServiceId); !serviceFound { - logger.Error(fmt.Sprintf("service %q does not exist", serviceConfig.ServiceId)) - return nil, types.ErrSupplierServiceNotFound.Wrapf("service %q does not exist", serviceConfig.ServiceId) + logger.Info(fmt.Sprintf("service %q does not exist", serviceConfig.ServiceId)) + return nil, status.Error( + codes.InvalidArgument, + types.ErrSupplierServiceNotFound.Wrapf("service %q does not exist", serviceConfig.ServiceId).Error(), + ) } } @@ -52,40 +57,42 @@ func (k msgServer) StakeSupplier(ctx context.Context, msg *types.MsgStakeSupplie // Ensure the signer is either the owner or the operator of the supplier. if !msg.IsSigner(supplier.OwnerAddress) && !msg.IsSigner(supplier.OperatorAddress) { - return nil, sharedtypes.ErrSharedUnauthorizedSupplierUpdate.Wrapf( - "signer address %s does not match owner address %s or supplier operator address %s", - msg.Signer, - msg.OwnerAddress, - msg.OperatorAddress, + return nil, status.Error( + codes.InvalidArgument, + sharedtypes.ErrSharedUnauthorizedSupplierUpdate.Wrapf( + "signer address %s does not match owner address %s or supplier operator address %s", + msg.Signer, msg.OwnerAddress, msg.OperatorAddress, + ).Error(), ) } // Ensure that only the owner can change the OwnerAddress. // (i.e. fail if owner address changed and the owner is not the msg signer) if !supplier.HasOwner(msg.OwnerAddress) && !msg.IsSigner(supplier.OwnerAddress) { - logger.Error("only the supplier owner is allowed to update the owner address") - - return nil, sharedtypes.ErrSharedUnauthorizedSupplierUpdate.Wrapf( + err = sharedtypes.ErrSharedUnauthorizedSupplierUpdate.Wrapf( "signer %q is not allowed to update the owner address %q", - msg.Signer, - supplier.OwnerAddress, + msg.Signer, supplier.OwnerAddress, ) + logger.Info(fmt.Sprintf("ERROR: %s", err)) + + return nil, status.Error(codes.InvalidArgument, err.Error()) } // Ensure that the operator addresses cannot be changed. This is because changing // it mid-session invalidates the current session. if !supplier.HasOperator(msg.OperatorAddress) { - logger.Error("updating the supplier's operator address forbidden") - - return nil, sharedtypes.ErrSharedUnauthorizedSupplierUpdate.Wrap( + err = sharedtypes.ErrSharedUnauthorizedSupplierUpdate.Wrap( "updating the operator address is forbidden, unstake then re-stake with the updated operator address", ) + logger.Info(fmt.Sprintf("ERROR: %s", err)) + + return nil, status.Error(codes.InvalidArgument, err.Error()) } currSupplierStake := *supplier.Stake if err = k.updateSupplier(ctx, &supplier, msg); err != nil { - logger.Error(fmt.Sprintf("could not update supplier for address %q due to error %v", msg.OperatorAddress, err)) - return nil, err + logger.Info(fmt.Sprintf("ERROR: could not update supplier for address %q due to error %v", msg.OperatorAddress, err)) + return nil, status.Error(codes.InvalidArgument, err.Error()) } coinsToEscrow, err = (*msg.Stake).SafeSub(currSupplierStake) if err != nil { @@ -99,22 +106,23 @@ func (k msgServer) StakeSupplier(ctx context.Context, msg *types.MsgStakeSupplie // Must always stake or upstake (> 0 delta) if coinsToEscrow.IsZero() { - logger.Warn(fmt.Sprintf("Signer %q must escrow more than 0 additional coins", msg.Signer)) - return nil, types.ErrSupplierInvalidStake.Wrapf("Signer %q must escrow more than 0 additional coins", msg.Signer) + err = types.ErrSupplierInvalidStake.Wrapf("Signer %q must escrow more than 0 additional coins", msg.Signer) + logger.Info(fmt.Sprintf("WARN: %s", err)) + return nil, status.Error(codes.InvalidArgument, err.Error()) } // Retrieve the account address of the message signer msgSignerAddress, err := sdk.AccAddressFromBech32(msg.Signer) if err != nil { - logger.Error(fmt.Sprintf("could not parse address %q", msg.Signer)) - return nil, err + logger.Info(fmt.Sprintf("ERROR: could not parse address %q", msg.Signer)) + return nil, status.Error(codes.InvalidArgument, err.Error()) } // Send the coins from the message signer account to the staked supplier pool err = k.bankKeeper.SendCoinsFromAccountToModule(ctx, msgSignerAddress, types.ModuleName, []sdk.Coin{coinsToEscrow}) if err != nil { - logger.Error(fmt.Sprintf("could not send %v coins from %q to %q module account due to %v", coinsToEscrow, msgSignerAddress, types.ModuleName, err)) - return nil, err + logger.Info(fmt.Sprintf("ERROR: could not send %v coins from %q to %q module account due to %v", coinsToEscrow, msgSignerAddress, types.ModuleName, err)) + return nil, status.Error(codes.InvalidArgument, err.Error()) } logger.Info(fmt.Sprintf("Successfully escrowed %v coins from %q to %q module account", coinsToEscrow, msgSignerAddress, types.ModuleName)) diff --git a/x/supplier/keeper/msg_server_stake_supplier_test.go b/x/supplier/keeper/msg_server_stake_supplier_test.go index 5c35f3625..a4c1b5815 100644 --- a/x/supplier/keeper/msg_server_stake_supplier_test.go +++ b/x/supplier/keeper/msg_server_stake_supplier_test.go @@ -157,7 +157,9 @@ func TestMsgServer_StakeSupplier_FailWithNonExistingService(t *testing.T) { // Stake the supplier & verify that it fails because the service does not exist. _, err := srv.StakeSupplier(ctx, stakeMsg) - require.ErrorIs(t, err, types.ErrSupplierServiceNotFound) + require.ErrorContains(t, err, types.ErrSupplierServiceNotFound.Wrapf( + "service %q does not exist", "newService", + ).Error()) } func TestMsgServer_StakeSupplier_OperatorAuthorizations(t *testing.T) { @@ -248,7 +250,10 @@ func TestMsgServer_StakeSupplier_OperatorAuthorizations(t *testing.T) { stakeMsgUpdateOwner.OwnerAddress = newOwnerAddress setStakeMsgSigner(stakeMsgUpdateOwner, operatorAddr) _, err = srv.StakeSupplier(ctx, stakeMsgUpdateOwner) - require.ErrorIs(t, err, sharedtypes.ErrSharedUnauthorizedSupplierUpdate) + require.ErrorContains(t, err, sharedtypes.ErrSharedUnauthorizedSupplierUpdate.Wrapf( + "signer %q is not allowed to update the owner address %q", + operatorAddr, ownerAddr, + ).Error()) // Update the supplier's owner address using the owner as a signer and verify that it succeeds. setStakeMsgSigner(stakeMsgUpdateOwner, ownerAddr) diff --git a/x/supplier/keeper/msg_server_update_param.go b/x/supplier/keeper/msg_server_update_param.go index 35efa6581..47e96f528 100644 --- a/x/supplier/keeper/msg_server_update_param.go +++ b/x/supplier/keeper/msg_server_update_param.go @@ -2,6 +2,10 @@ package keeper import ( "context" + "fmt" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" suppliertypes "github.com/pokt-network/poktroll/x/supplier/types" ) @@ -9,29 +13,53 @@ import ( // UpdateParam updates a single parameter in the proof module and returns // all active parameters. func (k msgServer) UpdateParam(ctx context.Context, msg *suppliertypes.MsgUpdateParam) (*suppliertypes.MsgUpdateParamResponse, error) { + logger := k.logger.With( + "method", "UpdateParam", + "param_name", msg.Name, + ) + if err := msg.ValidateBasic(); err != nil { - return nil, err + return nil, status.Error(codes.InvalidArgument, err.Error()) } if k.GetAuthority() != msg.Authority { - return nil, suppliertypes.ErrSupplierInvalidSigner.Wrapf("invalid authority; expected %s, got %s", k.GetAuthority(), msg.Authority) + return nil, status.Error( + codes.InvalidArgument, + suppliertypes.ErrSupplierInvalidSigner.Wrapf( + "invalid authority; expected %s, got %s", + k.GetAuthority(), msg.Authority, + ).Error(), + ) } - // TODO_UPNEXT(@bryanchriswhite, #612): uncomment & add a min_stake case. - - //params := k.GetParams(ctx) + params := k.GetParams(ctx) switch msg.Name { + case suppliertypes.ParamMinStake: + logger = logger.With("min_stake", msg.GetAsCoin()) + params.MinStake = msg.GetAsCoin() default: - return nil, suppliertypes.ErrSupplierParamInvalid.Wrapf("unsupported param %q", msg.Name) + return nil, status.Error( + codes.InvalidArgument, + suppliertypes.ErrSupplierParamInvalid.Wrapf("unsupported param %q", msg.Name).Error(), + ) + } + + // Perform a global validation on all params, which includes the updated param. + // This is needed to ensure that the updated param is valid in the context of all other params. + if err := params.Validate(); err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + + if err := k.SetParams(ctx, params); err != nil { + err = fmt.Errorf("unable to set params: %v", err) + logger.Error(err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } - //if err := k.SetParams(ctx, params); err != nil { - // return nil, err - //} - // - //updatedParams := k.GetParams(ctx) - //return &suppliertypes.MsgUpdateParamResponse{ - // Params: &updatedParams, - //}, nil + updatedParams := k.GetParams(ctx) + + return &suppliertypes.MsgUpdateParamResponse{ + Params: &updatedParams, + }, nil } diff --git a/x/supplier/keeper/msg_server_update_param_test.go b/x/supplier/keeper/msg_server_update_param_test.go new file mode 100644 index 000000000..39795eb82 --- /dev/null +++ b/x/supplier/keeper/msg_server_update_param_test.go @@ -0,0 +1,41 @@ +package keeper_test + +import ( + "testing" + + cosmostypes "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/stretchr/testify/require" + + "github.com/pokt-network/poktroll/app/volatile" + testkeeper "github.com/pokt-network/poktroll/testutil/keeper" + suppliertypes "github.com/pokt-network/poktroll/x/supplier/types" +) + +func TestMsgUpdateParam_UpdateMinStakeOnly(t *testing.T) { + expectedMinStake := cosmostypes.NewInt64Coin(volatile.DenomuPOKT, 420) + + // Set the parameters to their default values + k, msgSrv, ctx := setupMsgServer(t) + defaultParams := suppliertypes.DefaultParams() + require.NoError(t, k.SetParams(ctx, defaultParams)) + + // Ensure the default values are different from the new values we want to set + require.NotEqual(t, expectedMinStake, defaultParams.MinStake) + + // Update the min relay difficulty bits + updateParamMsg := &suppliertypes.MsgUpdateParam{ + Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(), + Name: suppliertypes.ParamMinStake, + AsType: &suppliertypes.MsgUpdateParam_AsCoin{AsCoin: &expectedMinStake}, + } + res, err := msgSrv.UpdateParam(ctx, updateParamMsg) + require.NoError(t, err) + + require.NotEqual(t, defaultParams.MinStake, res.Params.MinStake) + require.Equal(t, expectedMinStake.Amount, res.Params.MinStake.Amount) + + // Ensure the other parameters are unchanged + testkeeper.AssertDefaultParamsEqualExceptFields(t, &defaultParams, res.Params, string(suppliertypes.KeyMinStake)) +} diff --git a/x/supplier/keeper/msg_update_params_test.go b/x/supplier/keeper/msg_update_params_test.go index 9efd6db7d..5a0019a64 100644 --- a/x/supplier/keeper/msg_update_params_test.go +++ b/x/supplier/keeper/msg_update_params_test.go @@ -5,24 +5,24 @@ import ( "github.com/stretchr/testify/require" - "github.com/pokt-network/poktroll/x/supplier/types" + suppliertypes "github.com/pokt-network/poktroll/x/supplier/types" ) func TestMsgUpdateParams(t *testing.T) { k, ms, ctx := setupMsgServer(t) - params := types.DefaultParams() + params := suppliertypes.DefaultParams() require.NoError(t, k.SetParams(ctx, params)) // default params tests := []struct { desc string - params *types.MsgUpdateParams + params *suppliertypes.MsgUpdateParams shouldError bool expectedErrMsg string }{ { desc: "invalid: authority address invalid", - params: &types.MsgUpdateParams{ + params: &suppliertypes.MsgUpdateParams{ Authority: "invalid", Params: params, }, @@ -30,16 +30,26 @@ func TestMsgUpdateParams(t *testing.T) { expectedErrMsg: "invalid authority", }, { - desc: "send empty params", - params: &types.MsgUpdateParams{ + desc: "invalid: send empty params", + params: &suppliertypes.MsgUpdateParams{ Authority: k.GetAuthority(), - Params: types.Params{}, + Params: suppliertypes.Params{}, + }, + shouldError: true, + }, + { + desc: "valid: send minimal params", + params: &suppliertypes.MsgUpdateParams{ + Authority: k.GetAuthority(), + Params: suppliertypes.Params{ + MinStake: &suppliertypes.DefaultMinStake, + }, }, shouldError: false, }, { desc: "valid: send default params", - params: &types.MsgUpdateParams{ + params: &suppliertypes.MsgUpdateParams{ Authority: k.GetAuthority(), Params: params, }, diff --git a/x/supplier/keeper/params_test.go b/x/supplier/keeper/params_test.go index a2e5fefc5..3d74b7813 100644 --- a/x/supplier/keeper/params_test.go +++ b/x/supplier/keeper/params_test.go @@ -3,16 +3,60 @@ package keeper_test import ( "testing" + "cosmossdk.io/math" + cosmostypes "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" + "github.com/pokt-network/poktroll/app/volatile" keepertest "github.com/pokt-network/poktroll/testutil/keeper" - "github.com/pokt-network/poktroll/x/supplier/types" + suppliertypes "github.com/pokt-network/poktroll/x/supplier/types" ) func TestGetParams(t *testing.T) { supplierModuleKeepers, ctx := keepertest.SupplierKeeper(t) - params := types.DefaultParams() + params := suppliertypes.DefaultParams() require.NoError(t, supplierModuleKeepers.SetParams(ctx, params)) require.EqualValues(t, params, supplierModuleKeepers.Keeper.GetParams(ctx)) } + +func TestParams_ValidateMinStake(t *testing.T) { + tests := []struct { + desc string + minStake any + expectedErr error + }{ + { + desc: "invalid type", + minStake: "420", + expectedErr: suppliertypes.ErrSupplierParamInvalid.Wrapf("invalid parameter type: string"), + }, + { + desc: "MinStake less than zero", + minStake: &cosmostypes.Coin{ + Denom: volatile.DenomuPOKT, + Amount: math.NewInt(-1), + }, + expectedErr: suppliertypes.ErrSupplierParamInvalid.Wrapf( + "min_stake amount must be greater than 0: got -1%s", + volatile.DenomuPOKT, + ), + }, + { + desc: "valid MinStake", + minStake: &suppliertypes.DefaultMinStake, + }, + } + + for _, test := range tests { + t.Run(test.desc, func(t *testing.T) { + err := suppliertypes.ValidateMinStake(test.minStake) + if test.expectedErr != nil { + require.Error(t, err) + require.Contains(t, err.Error(), test.expectedErr.Error()) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/x/supplier/types/genesis_test.go b/x/supplier/types/genesis_test.go index 0e4301e3e..2b960fbb1 100644 --- a/x/supplier/types/genesis_test.go +++ b/x/supplier/types/genesis_test.go @@ -66,6 +66,7 @@ func TestGenesisState_Validate(t *testing.T) { { desc: "valid genesis state", genState: &types.GenesisState{ + Params: types.DefaultParams(), SupplierList: []sharedtypes.Supplier{ { OwnerAddress: addr1, @@ -87,6 +88,7 @@ func TestGenesisState_Validate(t *testing.T) { { desc: "invalid - zero supplier stake", genState: &types.GenesisState{ + Params: types.DefaultParams(), SupplierList: []sharedtypes.Supplier{ { OwnerAddress: addr1, @@ -107,6 +109,7 @@ func TestGenesisState_Validate(t *testing.T) { { desc: "invalid - negative supplier stake", genState: &types.GenesisState{ + Params: types.DefaultParams(), SupplierList: []sharedtypes.Supplier{ { OwnerAddress: addr1, @@ -127,6 +130,7 @@ func TestGenesisState_Validate(t *testing.T) { { desc: "invalid - wrong stake denom", genState: &types.GenesisState{ + Params: types.DefaultParams(), SupplierList: []sharedtypes.Supplier{ { OwnerAddress: addr1, @@ -147,6 +151,7 @@ func TestGenesisState_Validate(t *testing.T) { { desc: "invalid - missing denom", genState: &types.GenesisState{ + Params: types.DefaultParams(), SupplierList: []sharedtypes.Supplier{ { OwnerAddress: addr1, @@ -167,6 +172,7 @@ func TestGenesisState_Validate(t *testing.T) { { desc: "invalid - due to duplicated supplier operator address", genState: &types.GenesisState{ + Params: types.DefaultParams(), SupplierList: []sharedtypes.Supplier{ { OwnerAddress: addr1, @@ -187,6 +193,7 @@ func TestGenesisState_Validate(t *testing.T) { { desc: "invalid - due to nil supplier stake", genState: &types.GenesisState{ + Params: types.DefaultParams(), SupplierList: []sharedtypes.Supplier{ { OwnerAddress: addr1, @@ -207,6 +214,7 @@ func TestGenesisState_Validate(t *testing.T) { { desc: "invalid - due to missing supplier stake", genState: &types.GenesisState{ + Params: types.DefaultParams(), SupplierList: []sharedtypes.Supplier{ { OwnerAddress: addr1, @@ -227,6 +235,7 @@ func TestGenesisState_Validate(t *testing.T) { { desc: "invalid - missing services list", genState: &types.GenesisState{ + Params: types.DefaultParams(), SupplierList: []sharedtypes.Supplier{ { OwnerAddress: addr1, @@ -247,6 +256,7 @@ func TestGenesisState_Validate(t *testing.T) { { desc: "invalid - empty services list", genState: &types.GenesisState{ + Params: types.DefaultParams(), SupplierList: []sharedtypes.Supplier{ { OwnerAddress: addr1, @@ -267,6 +277,7 @@ func TestGenesisState_Validate(t *testing.T) { { desc: "invalid - invalid URL", genState: &types.GenesisState{ + Params: types.DefaultParams(), SupplierList: []sharedtypes.Supplier{ { OwnerAddress: addr1, @@ -304,6 +315,7 @@ func TestGenesisState_Validate(t *testing.T) { { desc: "invalid - invalid RPC Type", genState: &types.GenesisState{ + Params: types.DefaultParams(), SupplierList: []sharedtypes.Supplier{ { OwnerAddress: addr1, diff --git a/x/supplier/types/message_update_param.go b/x/supplier/types/message_update_param.go index 5819e1ed2..0e6a1cc03 100644 --- a/x/supplier/types/message_update_param.go +++ b/x/supplier/types/message_update_param.go @@ -27,6 +27,10 @@ func NewMsgUpdateParam(authority string, name string, asType any) *MsgUpdatePara } } +// ValidateBasic performs a basic validation of the MsgUpdateParam fields. It ensures: +// 1. The parameter name is supported. +// 2. The parameter type matches the expected type for a given parameter name. +// 3. The parameter value is valid (according to its respective validation function). func (msg *MsgUpdateParam) ValidateBasic() error { _, err := cosmostypes.AccAddressFromBech32(msg.Authority) if err != nil { @@ -40,10 +44,24 @@ func (msg *MsgUpdateParam) ValidateBasic() error { // Parameter name MUST be supported by this module. switch msg.Name { - // TODO_UPNEXT(@bryanchriswhite, #612): replace with min_stake param name and call validation function. - case "": - return nil + case ParamMinStake: + if err := msg.paramTypeIsCoin(); err != nil { + return err + } + return ValidateMinStake(msg.GetAsCoin()) default: return ErrSupplierParamInvalid.Wrapf("unsupported param %q", msg.Name) } } + +// paramTypeIsCoin checks if the parameter type is a Coin, returning an error if not. +func (msg *MsgUpdateParam) paramTypeIsCoin() error { + if _, ok := msg.AsType.(*MsgUpdateParam_AsCoin); !ok { + return ErrSupplierParamInvalid.Wrapf( + "invalid type for param %q expected %T, got %T", + msg.Name, &MsgUpdateParam_AsCoin{}, + msg.AsType, + ) + } + return nil +} diff --git a/x/supplier/types/message_update_param_test.go b/x/supplier/types/message_update_param_test.go index 96136ded1..b259020b7 100644 --- a/x/supplier/types/message_update_param_test.go +++ b/x/supplier/types/message_update_param_test.go @@ -28,17 +28,15 @@ func TestMsgUpdateParam_ValidateBasic(t *testing.T) { msg: MsgUpdateParam{ Authority: sample.AccAddress(), Name: "non_existent", - // TODO_UPNEXT(@bryanchriswhite, #612): replace with default min_stake. - AsType: &MsgUpdateParam_AsCoin{AsCoin: nil}, + AsType: &MsgUpdateParam_AsCoin{AsCoin: &DefaultMinStake}, }, err: ErrSupplierParamInvalid, }, { name: "valid: correct address, param name, and type", msg: MsgUpdateParam{ Authority: sample.AccAddress(), - Name: "", - // TODO_UPNEXT(@bryanchriswhite, #612): replace with default min_stake. - AsType: &MsgUpdateParam_AsCoin{AsCoin: nil}, + Name: ParamMinStake, + AsType: &MsgUpdateParam_AsCoin{AsCoin: &DefaultMinStake}, }, }, } diff --git a/x/supplier/types/params.go b/x/supplier/types/params.go index 95b0cf8a2..48a90f97d 100644 --- a/x/supplier/types/params.go +++ b/x/supplier/types/params.go @@ -1,8 +1,20 @@ package types -import paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" +import ( + cosmostypes "github.com/cosmos/cosmos-sdk/types" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" -var _ paramtypes.ParamSet = (*Params)(nil) + "github.com/pokt-network/poktroll/app/volatile" +) + +var ( + _ paramtypes.ParamSet = (*Params)(nil) + + KeyMinStake = []byte("MinStake") + ParamMinStake = "min_stake" + // TODO_MAINNET: Determine the default value. + DefaultMinStake = cosmostypes.NewInt64Coin("upokt", 1000000) // 1 POKT +) // ParamKeyTable the param key table for launch module func ParamKeyTable() paramtypes.KeyTable { @@ -10,21 +22,58 @@ func ParamKeyTable() paramtypes.KeyTable { } // NewParams creates a new Params instance -func NewParams() Params { - return Params{} +func NewParams(minStake *cosmostypes.Coin) Params { + return Params{ + MinStake: minStake, + } } // DefaultParams returns a default set of parameters func DefaultParams() Params { - return NewParams() + return NewParams(&DefaultMinStake) } // ParamSetPairs get the params.ParamSet func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { - return paramtypes.ParamSetPairs{} + return paramtypes.ParamSetPairs{ + paramtypes.NewParamSetPair( + KeyMinStake, + &p.MinStake, + ValidateMinStake, + ), + } } // Validate validates the set of params func (p Params) Validate() error { + if err := ValidateMinStake(p.MinStake); err != nil { + return err + } + + return nil +} + +// ValidateMinStake validates the MinStake param. +func ValidateMinStake(minStakeAny any) error { + minStakeCoin, ok := minStakeAny.(*cosmostypes.Coin) + if !ok { + return ErrSupplierParamInvalid.Wrapf("invalid parameter type: %T", minStakeAny) + } + + if minStakeCoin == nil { + return ErrSupplierParamInvalid.Wrapf("missing min_stake") + } + + if minStakeCoin.Denom != volatile.DenomuPOKT { + return ErrSupplierParamInvalid.Wrapf( + "invalid min_stake denom %q; expected %q", + minStakeCoin.Denom, volatile.DenomuPOKT, + ) + } + + if minStakeCoin.IsZero() || minStakeCoin.IsNegative() { + return ErrSupplierParamInvalid.Wrapf("min_stake amount must be greater than 0: got %s", minStakeCoin) + } + return nil } diff --git a/x/supplier/types/params.pb.go b/x/supplier/types/params.pb.go index 4400a9ef5..8a79db314 100644 --- a/x/supplier/types/params.pb.go +++ b/x/supplier/types/params.pb.go @@ -5,6 +5,7 @@ package types import ( fmt "fmt" + types "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" @@ -26,6 +27,9 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // Params defines the parameters for the module. type Params struct { + // min_stake is the minimum amount of uPOKT that a supplier must stake to be + // included in network sessions and remain staked. + MinStake *types.Coin `protobuf:"bytes,1,opt,name=min_stake,json=minStake,proto3" json:"min_stake" yaml:"min_stake"` } func (m *Params) Reset() { *m = Params{} } @@ -57,6 +61,13 @@ func (m *Params) XXX_DiscardUnknown() { var xxx_messageInfo_Params proto.InternalMessageInfo +func (m *Params) GetMinStake() *types.Coin { + if m != nil { + return m.MinStake + } + return nil +} + func init() { proto.RegisterType((*Params)(nil), "poktroll.supplier.Params") } @@ -64,19 +75,25 @@ func init() { func init() { proto.RegisterFile("poktroll/supplier/params.proto", fileDescriptor_60f7a8031a8c22d5) } var fileDescriptor_60f7a8031a8c22d5 = []byte{ - // 181 bytes of a gzipped FileDescriptorProto + // 273 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2b, 0xc8, 0xcf, 0x2e, 0x29, 0xca, 0xcf, 0xc9, 0xd1, 0x2f, 0x2e, 0x2d, 0x28, 0xc8, 0xc9, 0x4c, 0x2d, 0xd2, 0x2f, 0x48, 0x2c, 0x4a, 0xcc, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x84, 0xc9, 0xeb, 0xc1, 0xe4, 0xa5, 0x04, 0x13, 0x73, 0x33, 0xf3, 0xf2, 0xf5, 0xc1, 0x24, 0x44, 0x95, 0x94, 0x48, 0x7a, - 0x7e, 0x7a, 0x3e, 0x98, 0xa9, 0x0f, 0x62, 0x41, 0x44, 0x95, 0x74, 0xb9, 0xd8, 0x02, 0xc0, 0x66, - 0x59, 0x29, 0xbf, 0x58, 0x20, 0xcf, 0xd8, 0xf5, 0x7c, 0x83, 0x96, 0x14, 0xdc, 0xba, 0x0a, 0x84, - 0x85, 0x10, 0x45, 0x4e, 0xfe, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0x78, 0xe3, 0x91, - 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70, 0xe3, - 0xb1, 0x1c, 0x43, 0x94, 0x61, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x3e, - 0xc8, 0x10, 0xdd, 0xbc, 0xd4, 0x92, 0xf2, 0xfc, 0xa2, 0x6c, 0x7d, 0x6c, 0x26, 0x96, 0x54, 0x16, - 0xa4, 0x16, 0x27, 0xb1, 0x81, 0x9d, 0x61, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x2d, 0x7e, 0xc4, - 0x71, 0xe4, 0x00, 0x00, 0x00, + 0x7e, 0x7a, 0x3e, 0x98, 0xa9, 0x0f, 0x62, 0x41, 0x45, 0xe5, 0x92, 0xf3, 0x8b, 0x73, 0xf3, 0x8b, + 0xf5, 0x93, 0x12, 0x8b, 0x53, 0xf5, 0xcb, 0x0c, 0x93, 0x52, 0x4b, 0x12, 0x0d, 0xf5, 0x93, 0xf3, + 0x33, 0xf3, 0x20, 0xf2, 0x4a, 0x1d, 0x8c, 0x5c, 0x6c, 0x01, 0x60, 0xcb, 0x84, 0x22, 0xb9, 0x38, + 0x73, 0x33, 0xf3, 0xe2, 0x8b, 0x4b, 0x12, 0xb3, 0x53, 0x25, 0x18, 0x15, 0x18, 0x35, 0xb8, 0x8d, + 0x24, 0xf5, 0x20, 0xda, 0xf5, 0x40, 0xda, 0xf5, 0xa0, 0xda, 0xf5, 0x9c, 0xf3, 0x33, 0xf3, 0x9c, + 0x14, 0x5f, 0xdd, 0x93, 0x47, 0xa8, 0xff, 0x74, 0x4f, 0x5e, 0xa0, 0x32, 0x31, 0x37, 0xc7, 0x4a, + 0x09, 0x2e, 0xa4, 0x14, 0xc4, 0x91, 0x9b, 0x99, 0x17, 0x0c, 0x62, 0x5a, 0x29, 0xbf, 0x58, 0x20, + 0xcf, 0xd8, 0xf5, 0x7c, 0x83, 0x96, 0x14, 0xdc, 0xab, 0x15, 0x08, 0xcf, 0x42, 0xec, 0x77, 0xf2, + 0x3f, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x1b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, + 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0x0c, + 0xd3, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0x41, 0x86, 0xe8, 0xe6, 0xa5, + 0x96, 0x94, 0xe7, 0x17, 0x65, 0xeb, 0x63, 0x33, 0xb1, 0xa4, 0xb2, 0x20, 0xb5, 0x38, 0x89, 0x0d, + 0xec, 0x45, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc3, 0x4d, 0x0e, 0x37, 0x60, 0x01, 0x00, + 0x00, } func (this *Params) Equal(that interface{}) bool { @@ -98,6 +115,9 @@ func (this *Params) Equal(that interface{}) bool { } else if this == nil { return false } + if !this.MinStake.Equal(that1.MinStake) { + return false + } return true } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -120,6 +140,18 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.MinStake != nil { + { + size, err := m.MinStake.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } return len(dAtA) - i, nil } @@ -140,6 +172,10 @@ func (m *Params) Size() (n int) { } var l int _ = l + if m.MinStake != nil { + l = m.MinStake.Size() + n += 1 + l + sovParams(uint64(l)) + } return n } @@ -178,6 +214,42 @@ func (m *Params) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MinStake", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.MinStake == nil { + m.MinStake = &types.Coin{} + } + if err := m.MinStake.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:])