diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3b3fee315085..9641613e4b9e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -29,6 +29,7 @@ /server/v2/stf/ @testinginprod @kocubinski @cosmos/sdk-core-dev /server/v2/appmanager/ @testinginprod @facundomedica @cosmos/sdk-core-dev /server/v2/cometbft/ @facundomedica @sontrinh16 @cosmos/sdk-core-dev +/simsx @alpe @facundomedica @kocubinski @cosmos/sdk-core-dev /simapp/ @facundomedica @julienrbrt @cosmos/sdk-core-dev /simapp/v2/ @kocubinski @julienrbrt @cosmos/sdk-core-dev /store/ @cool-develope @kocubinski @cosmos/sdk-core-dev @@ -37,6 +38,7 @@ /tools/hubl @julienrbrt @JulianToledano @cosmos/sdk-core-dev /tools/cosmovisor @julienrbrt @facundomedica @cosmos/sdk-core-dev /tools/confix @julienrbrt @akhilkumarpilli @cosmos/sdk-core-dev +/tests/integration/aminojson @kocubinski @cosmos/sdk-core-dev # x modules diff --git a/.github/ISSUE_TEMPLATE/qa.md b/.github/ISSUE_TEMPLATE/qa.md index 6b0ef14807fe..c45a80ddb757 100644 --- a/.github/ISSUE_TEMPLATE/qa.md +++ b/.github/ISSUE_TEMPLATE/qa.md @@ -25,18 +25,20 @@ v without deliberation * [ ] Audit x/auth * [ ] Audit x/authz * [ ] Audit x/bank + * [ ] Audit x/bank/v2 * [ ] Audit x/circuit * [ ] Audit x/consensus * [ ] Audit x/crisis * [ ] Audit x/distribution * [ ] Audit x/evidence + * [ ] Audit x/epochs * [ ] Audit x/feegrant * [ ] Audit x/genutil * [ ] Audit x/gov * [ ] Audit x/group * [ ] Audit x/mint * [ ] Audit x/nft - * [ ] Audit x/simulation + * [ ] Audit x/protocolpool * [ ] Audit x/slashing * [ ] Audit x/staking * [ ] Audit x/tx diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 86fe6e1b2924..82413815cb76 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -187,6 +187,15 @@ updates: labels: - "A:automerge" - dependencies + - package-ecosystem: gomod + directory: "x/accounts/defaults/base" + schedule: + interval: weekly + day: wednesday + time: "02:45" + labels: + - "A:automerge" + - dependencies - package-ecosystem: gomod directory: "x/accounts/defaults/multisig" schedule: diff --git a/.github/pr_labeler.yml b/.github/pr_labeler.yml index 1b850dedc0a9..ed6ea1e9118d 100644 --- a/.github/pr_labeler.yml +++ b/.github/pr_labeler.yml @@ -10,8 +10,10 @@ "C:Keys": - client/keys/**/* "C:Simulations": + - types/simulation/**/* - x/simulation/**/* - x/*/simulation/**/* + - simsx/**/* "C:Store": - store/**/* "C:collections": @@ -28,6 +30,8 @@ - indexer/postgres/**/* "C:x/accounts": - x/accounts/**/* +"C:x/accounts/base": + - x/accounts/defaults/base/**/* "C:x/accounts/multisig": - x/accounts/defaults/multisig/**/* "C:x/accounts/lockup": diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8c77ba9700e7..46f3fd7bff7a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -937,6 +937,29 @@ jobs: with: projectBaseDir: x/accounts/ + test-x-accounts-base: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: "1.23" + check-latest: true + cache: true + cache-dependency-path: x/accounts/defaults/base/go.sum + - uses: technote-space/get-diff-action@v6.1.2 + id: git_diff + with: + PATTERNS: | + x/accounts/defaults/base/**/*.go + x/accounts/defaults/base/go.mod + x/accounts/defaults/base/go.sum + - name: tests + if: env.GIT_DIFF + run: | + cd x/accounts/defaults/base + go test -mod=readonly -timeout 30m -coverprofile=coverage.out -covermode=atomic -tags='norace ledger test_ledger_mock' ./... + test-x-accounts-lockup: runs-on: ubuntu-latest steps: diff --git a/.golangci.yml b/.golangci.yml index a976100278e9..9fa8a3398ac3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -13,7 +13,7 @@ linters: - dogsled - errcheck - errorlint - - exportloopref + - copyloopvar - gci - goconst - gocritic @@ -45,15 +45,15 @@ issues: - crypto/keys/secp256k1/internal/* - types/coin_regex.go exclude-rules: - - text: "ST1003:" + - text: "ST1003:" # We are fine with our current naming linters: - stylecheck # FIXME: Disabled until golangci-lint updates stylecheck with this fix: # https://github.com/dominikh/go-tools/issues/389 - - text: "ST1016:" + - text: "ST1016:" # Ok with inconsistent receiver names linters: - stylecheck - - path: "migrations" + - path: "migrations" # migraitions always use deprecated code text: "SA1019:" linters: - staticcheck @@ -72,9 +72,9 @@ issues: - text: "SA1019: params.SendEnabled is deprecated" # TODO remove once ready to remove from the sdk linters: - staticcheck - - text: "SA1029: Inappropriate key in context.WithValue" # TODO remove this when dependency is updated + - text: "G115: integer overflow conversion" # We are doing this everywhere. linters: - - staticcheck + - gosec - text: "leading space" linters: - nolintlint diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e6e974aef66..5d7602c02fb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,18 +43,24 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i ### Features * (baseapp) [#20291](https://github.com/cosmos/cosmos-sdk/pull/20291) Simulate nested messages. +* (cli) [#21372](https://github.com/cosmos/cosmos-sdk/pull/21372) Add a `bulk-add-genesis-account` genesis command to add many genesis accounts at once. +* (crypto/keyring) [#21653](https://github.com/cosmos/cosmos-sdk/pull/21653) New Linux-only backend that adds Linux kernel's `keyctl` support. * (runtime) [#21704](https://github.com/cosmos/cosmos-sdk/pull/21704) Add StoreLoader in simappv2. ### Improvements * (genutil) [#21701](https://github.com/cosmos/cosmos-sdk/pull/21701) Improved error messages for genesis validation. +* (sims)[#21613](https://github.com/cosmos/cosmos-sdk/pull/21613) Add sims2 framework and factory methods for simpler message factories in modules ### Bug Fixes * (baseapp) [#21256](https://github.com/cosmos/cosmos-sdk/pull/21256) Halt height will not commit the block indicated, meaning that if halt-height is set to 10, only blocks until 9 (included) will be committed. This is to go back to the original behavior before a change was introduced in v0.50.0. +* (runtime) [#21769](https://github.com/cosmos/cosmos-sdk/pull/21769) Fix baseapp options ordering to avoid overwriting options set by modules. ### API Breaking Changes +* (types/mempool) [#21744](https://github.com/cosmos/cosmos-sdk/pull/21744) Update types/mempool.Mempool interface to take decoded transactions. This avoid to decode the transaction twice. + ### Deprecated ## [v0.52.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.52.0) - 2024-XX-XX diff --git a/UPGRADING.md b/UPGRADING.md index d7c8752ae476..5f1859af1b13 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -44,7 +44,7 @@ To be able to simulate nested messages within a transaction, message types conta the nested messages. By implementing this interface, the BaseApp can simulate these nested messages during transaction simulation. -## [v0.52.x](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.52.0-alpha.0) +## [v0.52.x](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.52.0-beta.1) Documentation to migrate an application from v0.50.x to server/v2 is available elsewhere. It is additional to the changes described here. @@ -53,7 +53,7 @@ It is additional to the changes described here. In this section we describe the changes made in Cosmos SDK' SimApp. **These changes are directly applicable to your application wiring.** -Please read this section first, but for an exhaustive list of changes, refer to the [CHANGELOG](./simapp/CHANGELOG.md). +Please read this section first, but for an exhaustive list of changes, refer to the [CHANGELOG](https://github.com/cosmos/cosmos-sdk/blob/main/simapp/CHANGELOG.md). #### Client (`root.go`) @@ -195,7 +195,9 @@ Grpc-web embedded client has been removed from the server. If you would like to This indicates that Envoy has started and is ready to proxy requests. + 6. Update your client applications to connect to Envoy (http://localhost:8080 by default). + diff --git a/api/cosmos/auth/v1beta1/accounts.pulsar.go b/api/cosmos/auth/v1beta1/accounts.pulsar.go new file mode 100644 index 000000000000..1068e6db79cd --- /dev/null +++ b/api/cosmos/auth/v1beta1/accounts.pulsar.go @@ -0,0 +1,1095 @@ +// Code generated by protoc-gen-go-pulsar. DO NOT EDIT. +package authv1beta1 + +import ( + fmt "fmt" + runtime "github.com/cosmos/cosmos-proto/runtime" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoiface "google.golang.org/protobuf/runtime/protoiface" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + anypb "google.golang.org/protobuf/types/known/anypb" + io "io" + reflect "reflect" + sync "sync" +) + +var ( + md_QueryLegacyAccount protoreflect.MessageDescriptor +) + +func init() { + file_cosmos_auth_v1beta1_accounts_proto_init() + md_QueryLegacyAccount = File_cosmos_auth_v1beta1_accounts_proto.Messages().ByName("QueryLegacyAccount") +} + +var _ protoreflect.Message = (*fastReflection_QueryLegacyAccount)(nil) + +type fastReflection_QueryLegacyAccount QueryLegacyAccount + +func (x *QueryLegacyAccount) ProtoReflect() protoreflect.Message { + return (*fastReflection_QueryLegacyAccount)(x) +} + +func (x *QueryLegacyAccount) slowProtoReflect() protoreflect.Message { + mi := &file_cosmos_auth_v1beta1_accounts_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_QueryLegacyAccount_messageType fastReflection_QueryLegacyAccount_messageType +var _ protoreflect.MessageType = fastReflection_QueryLegacyAccount_messageType{} + +type fastReflection_QueryLegacyAccount_messageType struct{} + +func (x fastReflection_QueryLegacyAccount_messageType) Zero() protoreflect.Message { + return (*fastReflection_QueryLegacyAccount)(nil) +} +func (x fastReflection_QueryLegacyAccount_messageType) New() protoreflect.Message { + return new(fastReflection_QueryLegacyAccount) +} +func (x fastReflection_QueryLegacyAccount_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_QueryLegacyAccount +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_QueryLegacyAccount) Descriptor() protoreflect.MessageDescriptor { + return md_QueryLegacyAccount +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_QueryLegacyAccount) Type() protoreflect.MessageType { + return _fastReflection_QueryLegacyAccount_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_QueryLegacyAccount) New() protoreflect.Message { + return new(fastReflection_QueryLegacyAccount) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_QueryLegacyAccount) Interface() protoreflect.ProtoMessage { + return (*QueryLegacyAccount)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_QueryLegacyAccount) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_QueryLegacyAccount) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccount does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryLegacyAccount) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccount does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_QueryLegacyAccount) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccount does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryLegacyAccount) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccount does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryLegacyAccount) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccount does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_QueryLegacyAccount) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccount does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_QueryLegacyAccount) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in cosmos.auth.v1beta1.QueryLegacyAccount", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_QueryLegacyAccount) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryLegacyAccount) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_QueryLegacyAccount) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_QueryLegacyAccount) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*QueryLegacyAccount) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*QueryLegacyAccount) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*QueryLegacyAccount) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + 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++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryLegacyAccount: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryLegacyAccount: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +var ( + md_QueryLegacyAccountResponse protoreflect.MessageDescriptor + fd_QueryLegacyAccountResponse_account protoreflect.FieldDescriptor + fd_QueryLegacyAccountResponse_info protoreflect.FieldDescriptor +) + +func init() { + file_cosmos_auth_v1beta1_accounts_proto_init() + md_QueryLegacyAccountResponse = File_cosmos_auth_v1beta1_accounts_proto.Messages().ByName("QueryLegacyAccountResponse") + fd_QueryLegacyAccountResponse_account = md_QueryLegacyAccountResponse.Fields().ByName("account") + fd_QueryLegacyAccountResponse_info = md_QueryLegacyAccountResponse.Fields().ByName("info") +} + +var _ protoreflect.Message = (*fastReflection_QueryLegacyAccountResponse)(nil) + +type fastReflection_QueryLegacyAccountResponse QueryLegacyAccountResponse + +func (x *QueryLegacyAccountResponse) ProtoReflect() protoreflect.Message { + return (*fastReflection_QueryLegacyAccountResponse)(x) +} + +func (x *QueryLegacyAccountResponse) slowProtoReflect() protoreflect.Message { + mi := &file_cosmos_auth_v1beta1_accounts_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_QueryLegacyAccountResponse_messageType fastReflection_QueryLegacyAccountResponse_messageType +var _ protoreflect.MessageType = fastReflection_QueryLegacyAccountResponse_messageType{} + +type fastReflection_QueryLegacyAccountResponse_messageType struct{} + +func (x fastReflection_QueryLegacyAccountResponse_messageType) Zero() protoreflect.Message { + return (*fastReflection_QueryLegacyAccountResponse)(nil) +} +func (x fastReflection_QueryLegacyAccountResponse_messageType) New() protoreflect.Message { + return new(fastReflection_QueryLegacyAccountResponse) +} +func (x fastReflection_QueryLegacyAccountResponse_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_QueryLegacyAccountResponse +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_QueryLegacyAccountResponse) Descriptor() protoreflect.MessageDescriptor { + return md_QueryLegacyAccountResponse +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_QueryLegacyAccountResponse) Type() protoreflect.MessageType { + return _fastReflection_QueryLegacyAccountResponse_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_QueryLegacyAccountResponse) New() protoreflect.Message { + return new(fastReflection_QueryLegacyAccountResponse) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_QueryLegacyAccountResponse) Interface() protoreflect.ProtoMessage { + return (*QueryLegacyAccountResponse)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_QueryLegacyAccountResponse) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.Account != nil { + value := protoreflect.ValueOfMessage(x.Account.ProtoReflect()) + if !f(fd_QueryLegacyAccountResponse_account, value) { + return + } + } + if x.Info != nil { + value := protoreflect.ValueOfMessage(x.Info.ProtoReflect()) + if !f(fd_QueryLegacyAccountResponse_info, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_QueryLegacyAccountResponse) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.account": + return x.Account != nil + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.info": + return x.Info != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccountResponse does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryLegacyAccountResponse) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.account": + x.Account = nil + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.info": + x.Info = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccountResponse does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_QueryLegacyAccountResponse) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.account": + value := x.Account + return protoreflect.ValueOfMessage(value.ProtoReflect()) + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.info": + value := x.Info + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccountResponse does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryLegacyAccountResponse) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.account": + x.Account = value.Message().Interface().(*anypb.Any) + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.info": + x.Info = value.Message().Interface().(*BaseAccount) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccountResponse does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryLegacyAccountResponse) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.account": + if x.Account == nil { + x.Account = new(anypb.Any) + } + return protoreflect.ValueOfMessage(x.Account.ProtoReflect()) + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.info": + if x.Info == nil { + x.Info = new(BaseAccount) + } + return protoreflect.ValueOfMessage(x.Info.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccountResponse does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_QueryLegacyAccountResponse) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.account": + m := new(anypb.Any) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.info": + m := new(BaseAccount) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccountResponse does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_QueryLegacyAccountResponse) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in cosmos.auth.v1beta1.QueryLegacyAccountResponse", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_QueryLegacyAccountResponse) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryLegacyAccountResponse) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_QueryLegacyAccountResponse) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_QueryLegacyAccountResponse) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*QueryLegacyAccountResponse) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + if x.Account != nil { + l = options.Size(x.Account) + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.Info != nil { + l = options.Size(x.Info) + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*QueryLegacyAccountResponse) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if x.Info != nil { + encoded, err := options.Marshal(x.Info) + 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] = 0x12 + } + if x.Account != nil { + encoded, err := options.Marshal(x.Account) + 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 { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*QueryLegacyAccountResponse) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + 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++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryLegacyAccountResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryLegacyAccountResponse: 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 Account", 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.Account == nil { + x.Account = &anypb.Any{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Account); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Info", 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.Info == nil { + x.Info = &BaseAccount{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Info); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.0 +// protoc (unknown) +// source: cosmos/auth/v1beta1/accounts.proto + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// QueryLegacyAccount defines a query that can be implemented by an x/account +// to return an auth understandable representation of an account. +// This query is only used for accounts retro-compatibility at gRPC +// level, the state machine must not make any assumptions around this. +type QueryLegacyAccount struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *QueryLegacyAccount) Reset() { + *x = QueryLegacyAccount{} + if protoimpl.UnsafeEnabled { + mi := &file_cosmos_auth_v1beta1_accounts_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryLegacyAccount) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryLegacyAccount) ProtoMessage() {} + +// Deprecated: Use QueryLegacyAccount.ProtoReflect.Descriptor instead. +func (*QueryLegacyAccount) Descriptor() ([]byte, []int) { + return file_cosmos_auth_v1beta1_accounts_proto_rawDescGZIP(), []int{0} +} + +// QueryLegacyAccountResponse defines the response type of the +// `QueryLegacyAccount` query. +type QueryLegacyAccountResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // account represents the google.Protobuf.Any wrapped account + // the type wrapped by the any does not need to comply with the + // sdk.AccountI interface. + Account *anypb.Any `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"` + // info represents the account as a BaseAccount, this can return + // nil if the account cannot be represented as a base account. + // This is used in the gRPC QueryAccountInfo method. + Info *BaseAccount `protobuf:"bytes,2,opt,name=info,proto3" json:"info,omitempty"` +} + +func (x *QueryLegacyAccountResponse) Reset() { + *x = QueryLegacyAccountResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_cosmos_auth_v1beta1_accounts_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryLegacyAccountResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryLegacyAccountResponse) ProtoMessage() {} + +// Deprecated: Use QueryLegacyAccountResponse.ProtoReflect.Descriptor instead. +func (*QueryLegacyAccountResponse) Descriptor() ([]byte, []int) { + return file_cosmos_auth_v1beta1_accounts_proto_rawDescGZIP(), []int{1} +} + +func (x *QueryLegacyAccountResponse) GetAccount() *anypb.Any { + if x != nil { + return x.Account + } + return nil +} + +func (x *QueryLegacyAccountResponse) GetInfo() *BaseAccount { + if x != nil { + return x.Info + } + return nil +} + +var File_cosmos_auth_v1beta1_accounts_proto protoreflect.FileDescriptor + +var file_cosmos_auth_v1beta1_accounts_proto_rawDesc = []byte{ + 0x0a, 0x22, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x75, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x61, 0x75, 0x74, + 0x68, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x14, 0x0a, 0x12, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x65, 0x67, + 0x61, 0x63, 0x79, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x82, 0x01, 0x0a, 0x1a, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, + 0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x34, 0x0a, 0x04, 0x69, 0x6e, 0x66, + 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x61, + 0x73, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x42, + 0xc8, 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x61, + 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x0d, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, + 0x61, 0x31, 0x3b, 0x61, 0x75, 0x74, 0x68, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, + 0x03, 0x43, 0x41, 0x58, 0xaa, 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x75, + 0x74, 0x68, 0x2e, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x13, 0x43, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x75, 0x74, 0x68, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0xe2, 0x02, 0x1f, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x75, 0x74, 0x68, 0x5c, 0x56, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0xea, 0x02, 0x15, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x41, 0x75, 0x74, + 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_cosmos_auth_v1beta1_accounts_proto_rawDescOnce sync.Once + file_cosmos_auth_v1beta1_accounts_proto_rawDescData = file_cosmos_auth_v1beta1_accounts_proto_rawDesc +) + +func file_cosmos_auth_v1beta1_accounts_proto_rawDescGZIP() []byte { + file_cosmos_auth_v1beta1_accounts_proto_rawDescOnce.Do(func() { + file_cosmos_auth_v1beta1_accounts_proto_rawDescData = protoimpl.X.CompressGZIP(file_cosmos_auth_v1beta1_accounts_proto_rawDescData) + }) + return file_cosmos_auth_v1beta1_accounts_proto_rawDescData +} + +var file_cosmos_auth_v1beta1_accounts_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_cosmos_auth_v1beta1_accounts_proto_goTypes = []interface{}{ + (*QueryLegacyAccount)(nil), // 0: cosmos.auth.v1beta1.QueryLegacyAccount + (*QueryLegacyAccountResponse)(nil), // 1: cosmos.auth.v1beta1.QueryLegacyAccountResponse + (*anypb.Any)(nil), // 2: google.protobuf.Any + (*BaseAccount)(nil), // 3: cosmos.auth.v1beta1.BaseAccount +} +var file_cosmos_auth_v1beta1_accounts_proto_depIdxs = []int32{ + 2, // 0: cosmos.auth.v1beta1.QueryLegacyAccountResponse.account:type_name -> google.protobuf.Any + 3, // 1: cosmos.auth.v1beta1.QueryLegacyAccountResponse.info:type_name -> cosmos.auth.v1beta1.BaseAccount + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_cosmos_auth_v1beta1_accounts_proto_init() } +func file_cosmos_auth_v1beta1_accounts_proto_init() { + if File_cosmos_auth_v1beta1_accounts_proto != nil { + return + } + file_cosmos_auth_v1beta1_auth_proto_init() + if !protoimpl.UnsafeEnabled { + file_cosmos_auth_v1beta1_accounts_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryLegacyAccount); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cosmos_auth_v1beta1_accounts_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryLegacyAccountResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_cosmos_auth_v1beta1_accounts_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_cosmos_auth_v1beta1_accounts_proto_goTypes, + DependencyIndexes: file_cosmos_auth_v1beta1_accounts_proto_depIdxs, + MessageInfos: file_cosmos_auth_v1beta1_accounts_proto_msgTypes, + }.Build() + File_cosmos_auth_v1beta1_accounts_proto = out.File + file_cosmos_auth_v1beta1_accounts_proto_rawDesc = nil + file_cosmos_auth_v1beta1_accounts_proto_goTypes = nil + file_cosmos_auth_v1beta1_accounts_proto_depIdxs = nil +} diff --git a/baseapp/abci_test.go b/baseapp/abci_test.go index 07e7ea8199c9..fb61080916df 100644 --- a/baseapp/abci_test.go +++ b/baseapp/abci_test.go @@ -1589,7 +1589,6 @@ func TestABCI_GetBlockRetentionHeight(t *testing.T) { } for name, tc := range testCases { - tc := tc tc.bapp.SetParamStore(¶mStore{db: coretesting.NewMemDB()}) _, err := tc.bapp.InitChain(&abci.InitChainRequest{ @@ -2081,7 +2080,7 @@ func TestABCI_PrepareProposal_VoteExtensions(t *testing.T) { return nil, err } - cp := ctx.ConsensusParams() // nolint:staticcheck // ignore linting error + cp := ctx.ConsensusParams() //nolint:staticcheck // ignore linting error extsEnabled := cp.Feature.VoteExtensionsEnableHeight != nil && req.Height >= cp.Feature.VoteExtensionsEnableHeight.Value && cp.Feature.VoteExtensionsEnableHeight.Value != 0 if !extsEnabled { // check abci params diff --git a/baseapp/abci_utils.go b/baseapp/abci_utils.go index 63c13fa8620b..bc0cb9daccdd 100644 --- a/baseapp/abci_utils.go +++ b/baseapp/abci_utils.go @@ -47,7 +47,7 @@ func ValidateVoteExtensions( extCommit abci.ExtendedCommitInfo, ) error { // Get values from context - cp := ctx.ConsensusParams() // nolint:staticcheck // ignore linting error + cp := ctx.ConsensusParams() //nolint:staticcheck // ignore linting error currentHeight := ctx.HeaderInfo().Height chainID := ctx.HeaderInfo().ChainID commitInfo := ctx.CometInfo().LastCommit @@ -258,25 +258,31 @@ func (h *DefaultProposalHandler) SetTxSelector(ts TxSelector) { func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { return func(ctx sdk.Context, req *abci.PrepareProposalRequest) (*abci.PrepareProposalResponse, error) { var maxBlockGas uint64 - if b := ctx.ConsensusParams().Block; b != nil { // nolint:staticcheck // ignore linting error + if b := ctx.ConsensusParams().Block; b != nil { //nolint:staticcheck // ignore linting error maxBlockGas = uint64(b.MaxGas) } defer h.txSelector.Clear() + // decode transactions + decodedTxs := make([]sdk.Tx, len(req.Txs)) + for i, txBz := range req.Txs { + tx, err := h.txVerifier.TxDecode(txBz) + if err != nil { + return nil, err + } + + decodedTxs[i] = tx + } + // If the mempool is nil or NoOp we simply return the transactions // requested from CometBFT, which, by default, should be in FIFO order. // // Note, we still need to ensure the transactions returned respect req.MaxTxBytes. _, isNoOp := h.mempool.(mempool.NoOpMempool) if h.mempool == nil || isNoOp { - for _, txBz := range req.Txs { - tx, err := h.txVerifier.TxDecode(txBz) - if err != nil { - return nil, err - } - - stop := h.txSelector.SelectTxForProposal(ctx, uint64(req.MaxTxBytes), maxBlockGas, tx, txBz) + for i, tx := range decodedTxs { + stop := h.txSelector.SelectTxForProposal(ctx, uint64(req.MaxTxBytes), maxBlockGas, tx, req.Txs[i]) if stop { break } @@ -291,7 +297,7 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan selectedTxsNums int invalidTxs []sdk.Tx // invalid txs to be removed out of the loop to avoid dead lock ) - h.mempool.SelectBy(ctx, req.Txs, func(memTx sdk.Tx) bool { + h.mempool.SelectBy(ctx, decodedTxs, func(memTx sdk.Tx) bool { unorderedTx, ok := memTx.(sdk.TxWithUnordered) isUnordered := ok && unorderedTx.GetUnordered() txSignersSeqs := make(map[string]uint64) @@ -405,7 +411,7 @@ func (h *DefaultProposalHandler) ProcessProposalHandler() sdk.ProcessProposalHan var totalTxGas uint64 var maxBlockGas int64 - if b := ctx.ConsensusParams().Block; b != nil { // nolint:staticcheck // ignore linting error + if b := ctx.ConsensusParams().Block; b != nil { //nolint:staticcheck // ignore linting error maxBlockGas = b.MaxGas } diff --git a/baseapp/abci_utils_test.go b/baseapp/abci_utils_test.go index 7dae39542c18..e2c88c2431b7 100644 --- a/baseapp/abci_utils_test.go +++ b/baseapp/abci_utils_test.go @@ -691,6 +691,7 @@ func (s *ABCIUtilsTestSuite) TestDefaultProposalHandler_PriorityNonceMempoolTxSe ph := baseapp.NewDefaultProposalHandler(mp, app) for _, v := range tc.txInputs { + app.EXPECT().TxDecode(v.bz).Return(v.tx, nil).AnyTimes() app.EXPECT().PrepareProposalVerifyTx(v.tx).Return(v.bz, nil).AnyTimes() s.NoError(mp.Insert(s.ctx.WithPriority(v.priority), v.tx)) tc.req.Txs = append(tc.req.Txs, v.bz) diff --git a/baseapp/internal/protocompat/protocompat.go b/baseapp/internal/protocompat/protocompat.go index bd277e4a44f7..004efe635e2a 100644 --- a/baseapp/internal/protocompat/protocompat.go +++ b/baseapp/internal/protocompat/protocompat.go @@ -6,7 +6,7 @@ import ( "reflect" gogoproto "github.com/cosmos/gogoproto/proto" - "github.com/golang/protobuf/proto" // nolint: staticcheck // needed because gogoproto.Merge does not work consistently. See NOTE: comments. + "github.com/golang/protobuf/proto" //nolint: staticcheck // needed because gogoproto.Merge does not work consistently. See NOTE: comments. "google.golang.org/grpc" proto2 "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" diff --git a/baseapp/snapshot_test.go b/baseapp/snapshot_test.go index e6e6f1e5bd7d..e19b9cdfa9f5 100644 --- a/baseapp/snapshot_test.go +++ b/baseapp/snapshot_test.go @@ -245,7 +245,6 @@ func TestABCI_OfferSnapshot_Errors(t *testing.T) { }, abci.OFFER_SNAPSHOT_RESULT_REJECT}, } for name, tc := range testCases { - tc := tc t.Run(name, func(t *testing.T) { resp, err := suite.baseApp.OfferSnapshot(&abci.OfferSnapshotRequest{Snapshot: tc.snapshot}) require.NoError(t, err) diff --git a/client/cmd_test.go b/client/cmd_test.go index 559d31d39f40..31c7bf390b01 100644 --- a/client/cmd_test.go +++ b/client/cmd_test.go @@ -125,8 +125,6 @@ func TestSetCmdClientContextHandler(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { cmd := newCmd() _ = testutil.ApplyMockIODiscardOutErr(cmd) diff --git a/client/config/config_test.go b/client/config/config_test.go index 248ed47cea9c..81fe9e9f56a1 100644 --- a/client/config/config_test.go +++ b/client/config/config_test.go @@ -145,7 +145,6 @@ func TestConfigCmdEnvFlag(t *testing.T) { } for _, tc := range tt { - tc := tc t.Run(tc.name, func(t *testing.T) { testCmd := &cobra.Command{ Use: "test", diff --git a/client/flags/flags_test.go b/client/flags/flags_test.go index 5cc591bebbe7..657de9c0e658 100644 --- a/client/flags/flags_test.go +++ b/client/flags/flags_test.go @@ -22,8 +22,6 @@ func TestParseGasSetting(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { gs, err := flags.ParseGasSetting(tc.input) diff --git a/client/keys/add_ledger_test.go b/client/keys/add_ledger_test.go index 3d04cc5e3b92..d130127614f9 100644 --- a/client/keys/add_ledger_test.go +++ b/client/keys/add_ledger_test.go @@ -172,7 +172,6 @@ func Test_runAddCmdLedgerDryRun(t *testing.T) { } for _, tt := range testData { - tt := tt t.Run(tt.name, func(t *testing.T) { cmd := AddKeyCommand() cmd.Flags().AddFlagSet(Commands().PersistentFlags()) diff --git a/client/keys/add_test.go b/client/keys/add_test.go index 687aff609235..703bc5894c18 100644 --- a/client/keys/add_test.go +++ b/client/keys/add_test.go @@ -297,7 +297,6 @@ func Test_runAddCmdDryRun(t *testing.T) { }, } for _, tt := range testData { - tt := tt t.Run(tt.name, func(t *testing.T) { cmd := AddKeyCommand() cmd.Flags().AddFlagSet(Commands().PersistentFlags()) diff --git a/client/keys/list_test.go b/client/keys/list_test.go index 8f2752e5af9f..8660c0fe17d0 100644 --- a/client/keys/list_test.go +++ b/client/keys/list_test.go @@ -67,7 +67,6 @@ func Test_runListCmd(t *testing.T) { {"keybase: w/key", kbHome2, false}, } for _, tt := range testData { - tt := tt t.Run(tt.name, func(t *testing.T) { cmd.SetArgs([]string{ fmt.Sprintf("--%s=%s", flags.FlagKeyringDir, tt.kbDir), diff --git a/client/keys/parse_test.go b/client/keys/parse_test.go index 650cb7c501f0..88c9c31ec5e6 100644 --- a/client/keys/parse_test.go +++ b/client/keys/parse_test.go @@ -21,7 +21,6 @@ func TestParseKey(t *testing.T) { {"hex", []string{hexstr}, false}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { require.Equal(t, tt.wantErr, doParseKey(ParseKeyStringCommand(), "cosmos", tt.args) != nil) }) diff --git a/client/keys/show_test.go b/client/keys/show_test.go index 2f75430638a6..f309ad73b195 100644 --- a/client/keys/show_test.go +++ b/client/keys/show_test.go @@ -237,7 +237,6 @@ func Test_validateMultisigThreshold(t *testing.T) { {"1-2", args{2, 1}, true}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if err := validateMultisigThreshold(tt.args.k, tt.args.nKeys); (err != nil) != tt.wantErr { t.Errorf("validateMultisigThreshold() error = %v, wantErr %v", err, tt.wantErr) @@ -272,7 +271,6 @@ func Test_getBechKeyOut(t *testing.T) { {"cons", args{sdk.PrefixConsensus}, MkConsKeyOutput, false}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { output, err := getKeyOutput(ctx, tt.args.bechPrefix, k) if tt.wantErr { diff --git a/client/tx/aux_builder_test.go b/client/tx/aux_builder_test.go index f2083846ce38..6380f2d6ee50 100644 --- a/client/tx/aux_builder_test.go +++ b/client/tx/aux_builder_test.go @@ -214,7 +214,6 @@ func TestAuxTxBuilder(t *testing.T) { } for _, tc := range testcases { - tc := tc t.Run(tc.name, func(t *testing.T) { b = tx.NewAuxTxBuilder() err := tc.malleate() diff --git a/client/tx/tx_test.go b/client/tx/tx_test.go index 2669fe804983..21bfff6070b8 100644 --- a/client/tx/tx_test.go +++ b/client/tx/tx_test.go @@ -81,7 +81,6 @@ func TestCalculateGas(t *testing.T) { } for _, tc := range testCases { - stc := tc txCfg, _ := newTestTxConfig() defaultSignMode, err := signing.APISignModeToInternal(txCfg.SignModeHandler().DefaultMode()) require.NoError(t, err) @@ -90,16 +89,16 @@ func TestCalculateGas(t *testing.T) { WithChainID("test-chain"). WithTxConfig(txCfg).WithSignMode(defaultSignMode) - t.Run(stc.name, func(t *testing.T) { + t.Run(tc.name, func(t *testing.T) { mockClientCtx := mockContext{ gasUsed: tc.args.mockGasUsed, wantErr: tc.args.mockWantErr, } - simRes, gotAdjusted, err := CalculateGas(mockClientCtx, txf.WithGasAdjustment(stc.args.adjustment)) - if stc.expPass { + simRes, gotAdjusted, err := CalculateGas(mockClientCtx, txf.WithGasAdjustment(tc.args.adjustment)) + if tc.expPass { require.NoError(t, err) - require.Equal(t, simRes.GasInfo.GasUsed, stc.wantEstimate) - require.Equal(t, gotAdjusted, stc.wantAdjusted) + require.Equal(t, simRes.GasInfo.GasUsed, tc.wantEstimate) + require.Equal(t, gotAdjusted, tc.wantAdjusted) require.NotNil(t, simRes.Result) } else { require.Error(t, err) diff --git a/client/utils_test.go b/client/utils_test.go index c8cb93a9f56d..61bfb429cc3b 100644 --- a/client/utils_test.go +++ b/client/utils_test.go @@ -67,7 +67,6 @@ func TestPaginate(t *testing.T) { } for i, tc := range testCases { - i, tc := i, tc t.Run(tc.name, func(t *testing.T) { start, end := client.Paginate(tc.numObjs, tc.page, tc.limit, tc.defLimit) require.Equal(t, tc.expectedStart, start, "invalid result; test case #%d", i) diff --git a/client/v2/CHANGELOG.md b/client/v2/CHANGELOG.md index 5fae2c385bdc..831ee40ce922 100644 --- a/client/v2/CHANGELOG.md +++ b/client/v2/CHANGELOG.md @@ -43,6 +43,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [#18626](https://github.com/cosmos/cosmos-sdk/pull/18626) Support for off-chain signing and verification of a file. * [#18461](https://github.com/cosmos/cosmos-sdk/pull/18461) Support governance proposals. +### Improvements + +* [#21712](https://github.com/cosmos/cosmos-sdk/pull/21712) Marshal `type` field as proto message url in queries instead of amino name. + ### API Breaking Changes * [#17709](https://github.com/cosmos/cosmos-sdk/pull/17709) Address codecs have been removed from `autocli.AppOptions` and `flag.Builder`. Instead client/v2 uses the address codecs present in the context (introduced in [#17503](https://github.com/cosmos/cosmos-sdk/pull/17503)). diff --git a/client/v2/autocli/query.go b/client/v2/autocli/query.go index dc268b573654..166be5efebdc 100644 --- a/client/v2/autocli/query.go +++ b/client/v2/autocli/query.go @@ -119,11 +119,12 @@ func (b *Builder) BuildQueryMethodCommand(ctx context.Context, descriptor protor methodName := fmt.Sprintf("/%s/%s", serviceDescriptor.FullName(), descriptor.Name()) outputType := util.ResolveMessageType(b.TypeResolver, descriptor.Output()) encoderOptions := aminojson.EncoderOptions{ - Indent: " ", - EnumAsString: true, - DoNotSortFields: true, - TypeResolver: b.TypeResolver, - FileResolver: b.FileResolver, + Indent: " ", + EnumAsString: true, + DoNotSortFields: true, + AminoNameAsTypeURL: true, + TypeResolver: b.TypeResolver, + FileResolver: b.FileResolver, } cmd, err := b.buildMethodCommandCommon(descriptor, options, func(cmd *cobra.Command, input protoreflect.Message) error { diff --git a/client/v2/go.mod b/client/v2/go.mod index 64655bbfc946..e99563905ce6 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -4,7 +4,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/depinject v1.0.0 cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 cosmossdk.io/x/gov v0.0.0-20231113122742-912390d5fc4a @@ -26,7 +26,7 @@ require ( cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/log v1.4.1 // indirect cosmossdk.io/math v1.3.0 - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect filippo.io/edwards25519 v1.1.0 // indirect @@ -124,7 +124,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/client/v2/go.sum b/client/v2/go.sum index 37704b3a32de..ac1204539faa 100644 --- a/client/v2/go.sum +++ b/client/v2/go.sum @@ -6,8 +6,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 h1:XQJj9Dv9Gtze0l2TF79BU5lkP6MkUveTUuKICmxoz+o= cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190/go.mod h1:7WUGupOvmlHJoIMBz1JbObQxeo6/TDiuDBxmtod8HRg= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= @@ -412,8 +412,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/codec/amino_codec_test.go b/codec/amino_codec_test.go index 63df85e83782..f15da6a1456b 100644 --- a/codec/amino_codec_test.go +++ b/codec/amino_codec_test.go @@ -71,8 +71,6 @@ func TestAminoCodecMarshalJSONIndent(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { cdc := codec.NewAminoCodec(createTestCodec()) bz, err := cdc.MarshalJSONIndent(tc.input, "", " ") diff --git a/codec/codec_common_test.go b/codec/codec_common_test.go index 3280d2c195e3..4c0118f41994 100644 --- a/codec/codec_common_test.go +++ b/codec/codec_common_test.go @@ -122,7 +122,7 @@ func testMarshaling(t *testing.T, cdc interface { } for _, tc := range testCases { - tc := tc + m1 := mustMarshaler{cdc.Marshal, cdc.MustMarshal, cdc.Unmarshal, cdc.MustUnmarshal} m2 := mustMarshaler{cdc.MarshalLengthPrefixed, cdc.MustMarshalLengthPrefixed, cdc.UnmarshalLengthPrefixed, cdc.MustUnmarshalLengthPrefixed} m3 := mustMarshaler{ diff --git a/codec/unknownproto/unit_helpers_test.go b/codec/unknownproto/unit_helpers_test.go index 9c408a6d1f8a..b1564224892e 100644 --- a/codec/unknownproto/unit_helpers_test.go +++ b/codec/unknownproto/unit_helpers_test.go @@ -22,7 +22,6 @@ func TestWireTypeToString(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(fmt.Sprintf("wireType=%d", tt.typ), func(t *testing.T) { if g, w := wireTypeToString(tt.typ), tt.want; g != w { t.Fatalf("Mismatch:\nGot: %q\nWant: %q\n", g, w) diff --git a/codec/unknownproto/unknown_fields_test.go b/codec/unknownproto/unknown_fields_test.go index 7f2228e58436..85338f0595cb 100644 --- a/codec/unknownproto/unknown_fields_test.go +++ b/codec/unknownproto/unknown_fields_test.go @@ -223,7 +223,6 @@ func TestRejectUnknownFieldsRepeated(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { protoBlob, err := proto.Marshal(tt.in) if err != nil { @@ -280,7 +279,6 @@ func TestRejectUnknownFields_allowUnknownNonCriticals(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { blob, err := proto.Marshal(tt.in) if err != nil { @@ -483,7 +481,6 @@ func TestRejectUnknownFieldsNested(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { protoBlob, err := proto.Marshal(tt.in) if err != nil { @@ -634,7 +631,6 @@ func TestRejectUnknownFieldsFlat(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { blob, err := proto.Marshal(tt.in) if err != nil { diff --git a/collections/collections.go b/collections/collections.go index 10748e0bd935..2c67de4604aa 100644 --- a/collections/collections.go +++ b/collections/collections.go @@ -104,7 +104,7 @@ type Collection interface { // decoders and encoders to and from schema values and raw kv-store bytes. type collectionSchemaCodec struct { coll Collection - objectType schema.ObjectType + objectType schema.StateObjectType keyDecoder func([]byte) (any, error) valueDecoder func([]byte) (any, error) } diff --git a/collections/go.mod b/collections/go.mod index 3298820e8c12..cf96f875782e 100644 --- a/collections/go.mod +++ b/collections/go.mod @@ -3,9 +3,9 @@ module cosmossdk.io/collections go 1.23 require ( - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 - cosmossdk.io/schema v0.2.0 + cosmossdk.io/schema v0.3.0 github.com/stretchr/testify v1.9.0 github.com/tidwall/btree v1.7.0 pgregory.net/rapid v1.1.0 diff --git a/collections/go.sum b/collections/go.sum index 15437b213853..30b8599b383b 100644 --- a/collections/go.sum +++ b/collections/go.sum @@ -1,7 +1,7 @@ -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/collections/indexing.go b/collections/indexing.go index 9d83630bbd4f..5939aed5fea3 100644 --- a/collections/indexing.go +++ b/collections/indexing.go @@ -67,7 +67,7 @@ type moduleDecoder struct { collectionLookup *btree.Map[string, *collectionSchemaCodec] } -func (m moduleDecoder) decodeKV(update schema.KVPairUpdate) ([]schema.ObjectUpdate, error) { +func (m moduleDecoder) decodeKV(update schema.KVPairUpdate) ([]schema.StateObjectUpdate, error) { key := update.Key ks := string(key) var cd *collectionSchemaCodec @@ -87,32 +87,32 @@ func (m moduleDecoder) decodeKV(update schema.KVPairUpdate) ([]schema.ObjectUpda return cd.decodeKVPair(update) } -func (c collectionSchemaCodec) decodeKVPair(update schema.KVPairUpdate) ([]schema.ObjectUpdate, error) { +func (c collectionSchemaCodec) decodeKVPair(update schema.KVPairUpdate) ([]schema.StateObjectUpdate, error) { // strip prefix key := update.Key key = key[len(c.coll.GetPrefix()):] k, err := c.keyDecoder(key) if err != nil { - return []schema.ObjectUpdate{ + return []schema.StateObjectUpdate{ {TypeName: c.coll.GetName()}, }, err } if update.Remove { - return []schema.ObjectUpdate{ + return []schema.StateObjectUpdate{ {TypeName: c.coll.GetName(), Key: k, Delete: true}, }, nil } v, err := c.valueDecoder(update.Value) if err != nil { - return []schema.ObjectUpdate{ + return []schema.StateObjectUpdate{ {TypeName: c.coll.GetName(), Key: k}, }, err } - return []schema.ObjectUpdate{ + return []schema.StateObjectUpdate{ {TypeName: c.coll.GetName(), Key: k, Value: v}, }, nil } diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index 60cabab88dd1..c234cc971948 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -36,7 +36,12 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] - +## [v1.0.0-alpha.3](https://github.com/cosmos/cosmos-sdk/releases/tag/core%2Fv1.0.0-alpha.3) + +### Features + +* [#21719](https://github.com/cosmos/cosmos-sdk/pull/21719) Make `core/event` as a type alias of `schema/appdata`. + ## [v1.0.0-alpha.2](https://github.com/cosmos/cosmos-sdk/releases/tag/core%2Fv1.0.0-alpha.2) ### Features diff --git a/core/README.md b/core/README.md index 6ab95a67a6f1..f54197bd7be5 100644 --- a/core/README.md +++ b/core/README.md @@ -10,7 +10,7 @@ Key features and principles: 4. Modules depend solely on core APIs for maximum compatibility. 5. New API additions undergo thorough consideration to maintain stability. 6. Adheres to a no-breaking-changes policy for reliable dependency management. -7. Aimed to have zero dependencies, ensuring a lightweight and self-contained foundation. +7. Aimed to only depend on `schema`, ensuring a lightweight and self-contained foundation. The core module offers the [appmodule](https://pkg.go.dev/cosmossdk.io/core/appmodule) and [appmodule/v2](https://pkg.go.dev/cosmossdk.io/core/appmodule/v2) packages that include APIs to describe how modules can be written. Additionally, it contains all core services APIs that can be used in modules to interact with the SDK, majoritarily via the `appmodule.Environment` struct. diff --git a/core/event/event.go b/core/event/event.go index 4304e6e2b4af..de8fe739b379 100644 --- a/core/event/event.go +++ b/core/event/event.go @@ -1,29 +1,24 @@ package event +import "cosmossdk.io/schema/appdata" + // Attribute is a kv-pair event attribute. -type Attribute struct { - Key, Value string -} +type Attribute = appdata.EventAttribute func NewAttribute(key, value string) Attribute { return Attribute{Key: key, Value: value} } // Events represents a list of events. -type Events struct { - Events []Event -} +type Events = appdata.EventData func NewEvents(events ...Event) Events { return Events{Events: events} } // Event defines how an event will emitted -type Event struct { - Type string - Attributes []Attribute -} +type Event = appdata.Event func NewEvent(ty string, attrs ...Attribute) Event { - return Event{Type: ty, Attributes: attrs} + return Event{Type: ty, Attributes: func() ([]Attribute, error) { return attrs, nil }} } diff --git a/core/go.mod b/core/go.mod index 8f691cc75063..61b97a200010 100644 --- a/core/go.mod +++ b/core/go.mod @@ -1,9 +1,11 @@ module cosmossdk.io/core -// Core is meant to have zero dependencies, so we can use it as a dependency +// Core is meant to have only a dependency on cosmossdk.io/schema, so we can use it as a dependency // in other modules without having to worry about circular dependencies. go 1.23 +require cosmossdk.io/schema v0.3.0 + // Version tagged too early and incompatible with v0.50 (latest at the time of tagging) retract v0.12.0 diff --git a/core/go.sum b/core/go.sum index e69de29bb2d1..18e538dae2df 100644 --- a/core/go.sum +++ b/core/go.sum @@ -0,0 +1,2 @@ +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= diff --git a/crypto/hd/hdpath_test.go b/crypto/hd/hdpath_test.go index cce81df86f20..fa203911a58c 100644 --- a/crypto/hd/hdpath_test.go +++ b/crypto/hd/hdpath_test.go @@ -107,9 +107,7 @@ func TestCreateHDPath(t *testing.T) { {"m/44'/114'/1'/1/0", args{114, 1, 1}, hd.BIP44Params{Purpose: 44, CoinType: 114, Account: 1, AddressIndex: 1}}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { - tt := tt require.Equal(t, tt.want, *hd.CreateHDPath(tt.args.coinType, tt.args.account, tt.args.index)) }) } @@ -170,7 +168,6 @@ func TestDeriveHDPathRange(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.path, func(t *testing.T) { master, ch := hd.ComputeMastersFromSeed(seed) _, err := hd.DerivePrivateKeyForPath(master, ch, tt.path) @@ -297,7 +294,6 @@ func TestDerivePrivateKeyForPathDoNotCrash(t *testing.T) { } for _, path := range paths { - path := path t.Run(path, func(t *testing.T) { _, _ = hd.DerivePrivateKeyForPath([32]byte{}, [32]byte{}, path) }) diff --git a/crypto/keyring/doc.go b/crypto/keyring/doc.go index a3bc8d8824ac..87a9e0908b36 100644 --- a/crypto/keyring/doc.go +++ b/crypto/keyring/doc.go @@ -33,6 +33,8 @@ // https://github.com/KDE/kwallet // pass This backend uses the pass command line utility to store and retrieve keys: // https://www.passwordstore.org/ +// keyctl This backend leverages the Linux's kernel security key management system +// to store cryptographic keys securely in memory. This is available on Linux only. // test This backend stores keys insecurely to disk. It does not prompt for a password to // be unlocked and it should be used only for testing purposes. // memory Same instance as returned by NewInMemory. This backend uses a transient storage. Keys diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index aee52a62563c..ef3b0a16df08 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -147,23 +147,6 @@ type Exporter interface { // Option overrides keyring configuration options. type Option func(options *Options) -// Options define the options of the Keyring. -type Options struct { - // supported signing algorithms for keyring - SupportedAlgos SigningAlgoList - // supported signing algorithms for Ledger - SupportedAlgosLedger SigningAlgoList - // define Ledger Derivation function - LedgerDerivation func() (ledger.SECP256K1, error) - // define Ledger key generation function - LedgerCreateKey func([]byte) types.PubKey - // define Ledger app name - LedgerAppName string - // indicate whether Ledger should skip DER Conversion on signature, - // depending on which format (DER or BER) the Ledger app returns signatures - LedgerSigSkipDERConv bool -} - // NewInMemory creates a transient keyring useful for testing // purposes and on-the-fly key generation. // Keybase options can be applied when generating this new Keybase. @@ -180,7 +163,7 @@ func NewInMemoryWithKeyring(kr keyring.Keyring, cdc codec.Codec, opts ...Option) // New creates a new instance of a keyring. // Keyring options can be applied when generating the new instance. // Available backends are "os", "file", "kwallet", "memory", "pass", "test". -func New( +func newKeyringGeneric( appName, backend, rootDir string, userInput io.Reader, cdc codec.Codec, opts ...Option, ) (Keyring, error) { var ( diff --git a/crypto/keyring/keyring_linux.go b/crypto/keyring/keyring_linux.go new file mode 100644 index 000000000000..7db47961bab1 --- /dev/null +++ b/crypto/keyring/keyring_linux.go @@ -0,0 +1,84 @@ +//go:build linux +// +build linux + +package keyring + +import ( + "fmt" + "io" + + "github.com/99designs/keyring" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/crypto/ledger" + "github.com/cosmos/cosmos-sdk/crypto/types" +) + +// Linux-only backend options. +const BackendKeyctl = "keyctl" + +func KeyctlScopeUser(options *Options) { setKeyctlScope(options, "user") } +func KeyctlScopeUserSession(options *Options) { setKeyctlScope(options, "usersession") } +func KeyctlScopeSession(options *Options) { setKeyctlScope(options, "session") } +func KeyctlScopeProcess(options *Options) { setKeyctlScope(options, "process") } +func KeyctlScopeThread(options *Options) { setKeyctlScope(options, "thread") } + +// Options define the options of the Keyring. +type Options struct { + // supported signing algorithms for keyring + SupportedAlgos SigningAlgoList + // supported signing algorithms for Ledger + SupportedAlgosLedger SigningAlgoList + // define Ledger Derivation function + LedgerDerivation func() (ledger.SECP256K1, error) + // define Ledger key generation function + LedgerCreateKey func([]byte) types.PubKey + // define Ledger app name + LedgerAppName string + // indicate whether Ledger should skip DER Conversion on signature, + // depending on which format (DER or BER) the Ledger app returns signatures + LedgerSigSkipDERConv bool + // KeyctlScope defines the scope of the keyctl's keyring. + KeyctlScope string +} + +func newKeyctlBackendConfig(appName, _ string, _ io.Reader, opts ...Option) keyring.Config { + options := Options{ + KeyctlScope: keyctlDefaultScope, // currently "process" + } + + for _, optionFn := range opts { + optionFn(&options) + } + + return keyring.Config{ + AllowedBackends: []keyring.BackendType{keyring.KeyCtlBackend}, + ServiceName: appName, + KeyCtlScope: options.KeyctlScope, + } +} + +// New creates a new instance of a keyring. +// Keyring options can be applied when generating the new instance. +// Available backends are "os", "file", "kwallet", "memory", "pass", "test", "keyctl". +func New( + appName, backend, rootDir string, userInput io.Reader, cdc codec.Codec, opts ...Option, +) (Keyring, error) { + if backend != BackendKeyctl { + return newKeyringGeneric(appName, backend, rootDir, userInput, cdc, opts...) + } + + db, err := keyring.Open(newKeyctlBackendConfig(appName, "", userInput, opts...)) + if err != nil { + return nil, fmt.Errorf("couldn't open keyring for %q: %w", appName, err) + } + + return newKeystore(db, cdc, backend, opts...), nil +} + +func setKeyctlScope(options *Options, scope string) { options.KeyctlScope = scope } + +// this is private as it is meant to be here for SDK devs convenience +// as the user does not need to pick any default when he wants to +// initialize keyctl with the default scope. +const keyctlDefaultScope = "process" diff --git a/crypto/keyring/keyring_linux_test.go b/crypto/keyring/keyring_linux_test.go new file mode 100644 index 000000000000..a6695b6b9471 --- /dev/null +++ b/crypto/keyring/keyring_linux_test.go @@ -0,0 +1,51 @@ +//go:build linux +// +build linux + +package keyring + +import ( + "errors" + "io" + "strings" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/codec" +) + +func TestNewKeyctlKeyring(t *testing.T) { + cdc := getCodec() + + tests := []struct { + name string + appName string + backend string + dir string + userInput io.Reader + cdc codec.Codec + expectedErr error + }{ + { + name: "keyctl backend", + appName: "cosmos", + backend: BackendKeyctl, + dir: t.TempDir(), + userInput: strings.NewReader(""), + cdc: cdc, + expectedErr: nil, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + kr, err := New(tt.appName, tt.backend, tt.dir, tt.userInput, tt.cdc) + if tt.expectedErr == nil { + require.NoError(t, err) + } else { + require.Error(t, err) + require.Nil(t, kr) + require.True(t, errors.Is(err, tt.expectedErr)) + } + }) + } +} diff --git a/crypto/keyring/keyring_other.go b/crypto/keyring/keyring_other.go new file mode 100644 index 000000000000..9c25a1e954e2 --- /dev/null +++ b/crypto/keyring/keyring_other.go @@ -0,0 +1,35 @@ +//go:build !linux +// +build !linux + +package keyring + +import ( + "io" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/crypto/ledger" + "github.com/cosmos/cosmos-sdk/crypto/types" +) + +// Options define the options of the Keyring. +type Options struct { + // supported signing algorithms for keyring + SupportedAlgos SigningAlgoList + // supported signing algorithms for Ledger + SupportedAlgosLedger SigningAlgoList + // define Ledger Derivation function + LedgerDerivation func() (ledger.SECP256K1, error) + // define Ledger key generation function + LedgerCreateKey func([]byte) types.PubKey + // define Ledger app name + LedgerAppName string + // indicate whether Ledger should skip DER Conversion on signature, + // depending on which format (DER or BER) the Ledger app returns signatures + LedgerSigSkipDERConv bool +} + +func New( + appName, backend, rootDir string, userInput io.Reader, cdc codec.Codec, opts ...Option, +) (Keyring, error) { + return newKeyringGeneric(appName, backend, rootDir, userInput, cdc, opts...) +} diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 519cd01142f8..850cbcbafe04 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -2003,7 +2003,7 @@ func TestRenameKey(t *testing.T) { } for _, tc := range testCases { - tc := tc + kr := newKeyring(t, "testKeyring") t.Run(tc.name, func(t *testing.T) { tc.run(kr) diff --git a/crypto/keyring/signing_algorithms_test.go b/crypto/keyring/signing_algorithms_test.go index 624e491d098a..1ac7d9cc352e 100644 --- a/crypto/keyring/signing_algorithms_test.go +++ b/crypto/keyring/signing_algorithms_test.go @@ -36,7 +36,6 @@ func TestNewSigningAlgoByString(t *testing.T) { list := SigningAlgoList{hd.Secp256k1} for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { algorithm, err := NewSigningAlgoFromString(tt.algoStr, list) if tt.isSupported { diff --git a/crypto/keys/secp256k1/secp256k1.go b/crypto/keys/secp256k1/secp256k1.go index 4073684076ff..927b0eafe9e1 100644 --- a/crypto/keys/secp256k1/secp256k1.go +++ b/crypto/keys/secp256k1/secp256k1.go @@ -12,7 +12,7 @@ import ( "github.com/cometbft/cometbft/crypto" secp256k1dcrd "github.com/decred/dcrd/dcrec/secp256k1/v4" "gitlab.com/yawning/secp256k1-voi/secec" - "golang.org/x/crypto/ripemd160" //nolint: staticcheck // keep around for backwards compatibility + "golang.org/x/crypto/ripemd160" //nolint:staticcheck,gosec // keep around for backwards compatibility errorsmod "cosmossdk.io/errors" @@ -173,8 +173,8 @@ func (pubKey *PubKey) Address() crypto.Address { } sha := sha256.Sum256(pubKey.Key) - hasherRIPEMD160 := ripemd160.New() - hasherRIPEMD160.Write(sha[:]) // does not error + hasherRIPEMD160 := ripemd160.New() //nolint:gosec // keep around for backwards compatibility + hasherRIPEMD160.Write(sha[:]) // does not error return crypto.Address(hasherRIPEMD160.Sum(nil)) } diff --git a/crypto/keys/secp256k1/secp256k1_internal_test.go b/crypto/keys/secp256k1/secp256k1_internal_test.go index 08afa6014e4b..c0df3ed5286b 100644 --- a/crypto/keys/secp256k1/secp256k1_internal_test.go +++ b/crypto/keys/secp256k1/secp256k1_internal_test.go @@ -27,7 +27,6 @@ func Test_genPrivKey(t *testing.T) { {"valid because 0 < 1 < N", validOne, false}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if tt.shouldPanic { require.Panics(t, func() { diff --git a/crypto/keys/secp256k1/secp256k1_test.go b/crypto/keys/secp256k1/secp256k1_test.go index 76db9ec72306..bafab8b9f3af 100644 --- a/crypto/keys/secp256k1/secp256k1_test.go +++ b/crypto/keys/secp256k1/secp256k1_test.go @@ -255,7 +255,6 @@ func TestGenPrivKeyFromSecret(t *testing.T) { {"another seed used in cosmos tests #3", []byte("")}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { gotPrivKey := secp256k1.GenPrivKeyFromSecret(tt.secret) require.NotNil(t, gotPrivKey) diff --git a/crypto/types/compact_bit_array_test.go b/crypto/types/compact_bit_array_test.go index 4831e8e681ea..1f7f276cff22 100644 --- a/crypto/types/compact_bit_array_test.go +++ b/crypto/types/compact_bit_array_test.go @@ -58,7 +58,6 @@ func TestBitArrayEqual(t *testing.T) { {name: "different should not be equal", b1: big1, b2: big2, eq: false}, } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { eq := tc.b1.Equal(tc.b2) require.Equal(t, tc.eq, eq) @@ -102,7 +101,6 @@ func TestJSONMarshalUnmarshal(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.bA.String(), func(t *testing.T) { bz, err := json.Marshal(tc.bA) require.NoError(t, err) @@ -162,7 +160,6 @@ func TestCompactMarshalUnmarshal(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.bA.String(), func(t *testing.T) { bz := tc.bA.CompactMarshal() @@ -209,8 +206,6 @@ func TestCompactBitArrayNumOfTrueBitsBefore(t *testing.T) { {`"______________xx"`, []int{14, 15}, []int{0, 1}}, } for tcIndex, tc := range testCases { - tc := tc - tcIndex := tcIndex t.Run(tc.marshalledBA, func(t *testing.T) { var bA *CompactBitArray err := json.Unmarshal([]byte(tc.marshalledBA), &bA) @@ -283,7 +278,6 @@ func TestNewCompactBitArrayCrashWithLimits(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(fmt.Sprintf("%d", tt.in), func(t *testing.T) { got := NewCompactBitArray(tt.in) if g := got != nil; g != tt.mustPass { diff --git a/docs/build/building-modules/14-simulator.md b/docs/build/building-modules/14-simulator.md index 0d8b4c5a861a..966df4cb8952 100644 --- a/docs/build/building-modules/14-simulator.md +++ b/docs/build/building-modules/14-simulator.md @@ -38,6 +38,8 @@ and then unmarshals the value from the `KVPair` to the type provided. You can use the example [here](https://github.com/cosmos/cosmos-sdk/blob/main/x/distribution/simulation/decoder.go) from the distribution module to implement your store decoders. +If the module uses the `collections` package, you can use the example [here](https://github.com/cosmos/cosmos-sdk/blob/23cf89cce1882ba9c8280e64735ae200504bfdce/x/bank/module.go#L166) from the Bank module to implement your store decoders. + ### Randomized genesis The simulator tests different scenarios and values for genesis parameters @@ -61,33 +63,33 @@ Operations on the simulation are simulated using the full [transaction cycle](.. Shown below is how weights are set: ```go reference -https://github.com/cosmos/cosmos-sdk/blob/release/v0.50.x/x/staking/simulation/operations.go#L19-L86 +https://github.com/cosmos/cosmos-sdk/blob/23cf89cce1882ba9c8280e64735ae200504bfdce/x/staking/depinject.go#L144-L154 ``` As you can see, the weights are predefined in this case. Options exist to override this behavior with different weights. One option is to use `*rand.Rand` to define a random weight for the operation, or you can inject your own predefined weights. -Here is how one can override the above package `simappparams`. - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/release/v0.51.x/Makefile#L292-L334 -``` - The SDK simulations can be executed like normal tests in Go from the shell or within an IDE. Make sure that you pass the `-tags='sims` parameter to enable them and other params that make sense for your scenario. +```go reference +https://github.com/cosmos/cosmos-sdk/blob/23cf89cce1882ba9c8280e64735ae200504bfdce/scripts/build/simulations.mk#L19 +``` ### Random proposal contents Randomized governance proposals are also supported on the Cosmos SDK simulator. Each -module must define the governance proposal `Content`s that they expose and register -them to be used on the parameters. +module must register the message to be used for governance proposals. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/23cf89cce1882ba9c8280e64735ae200504bfdce/x/staking/depinject.go#L139-L142 +``` ## Registering simulation functions Now that all the required functions are defined, we need to integrate them into the module pattern within the `module.go`: ```go reference -https://github.com/cosmos/cosmos-sdk/blob/release/v0.50.x/x/distribution/module.go#L180-L203 +https://github.com/cosmos/cosmos-sdk/blob/23cf89cce1882ba9c8280e64735ae200504bfdce/x/staking/depinject.go#L127-L154 ``` ## App Simulator manager @@ -117,7 +119,7 @@ func NewCustomApp(...) { gov.NewAppModule(app.govKeeper, app.accountKeeper, app.supplyKeeper), mint.NewAppModule(app.mintKeeper), distr.NewAppModule(app.distrKeeper, app.accountKeeper, app.supplyKeeper, app.stakingKeeper), - staking.NewAppModule(app.stakingKeeper, app.accountKeeper, app.supplyKeeper), + staking.NewAppModule(cdc, app.stakingKeeper), slashing.NewAppModule(app.slashingKeeper, app.accountKeeper, app.stakingKeeper), ) @@ -133,5 +135,5 @@ The simulations provide deterministic behaviour already. The integration with th can be done at a high level with the deterministic pseudo random number generator where the fuzzer provides varying numbers. ```go reference -https://github.com/cosmos/cosmos-sdk/blob/release/v0.51.x/Makefile#L352-L355 +https://github.com/cosmos/cosmos-sdk/blob/23cf89cce1882ba9c8280e64735ae200504bfdce/scripts/build/simulations.mk#L80-L84 ``` diff --git a/docs/build/tooling/00-protobuf.md b/docs/build/tooling/00-protobuf.md index 01afbb342c15..d9a210a78577 100644 --- a/docs/build/tooling/00-protobuf.md +++ b/docs/build/tooling/00-protobuf.md @@ -98,7 +98,7 @@ https://github.com/cosmos/cosmos-sdk/blob/main/proto/buf.lock#L1-L16 #### `buf.yaml` -`buf.yaml` defines the [name of your package](https://github.com/cosmos/cosmos-sdk/blob/main/proto/buf.yaml#L3), which [breakage checker](https://docs.buf.build/tour/detect-breaking-changes) to use and how to [lint your protobuf files](https://buf.build/docs/tutorials/getting-started-with-buf-cli#lint-your-api). +`buf.yaml` defines the [name of your package](https://github.com/cosmos/cosmos-sdk/blob/main/proto/buf.yaml#L3), which [breakage checker](https://buf.build/docs/tutorials/getting-started-with-buf-cli#detect-breaking-changes) to use and how to [lint your protobuf files](https://buf.build/docs/tutorials/getting-started-with-buf-cli#lint-your-api). ```go reference https://github.com/cosmos/cosmos-sdk/blob/main/proto/buf.yaml#L1-L24 diff --git a/docs/learn/advanced/12-simulation.md b/docs/learn/advanced/12-simulation.md index dfbcddd0d29f..c30d398c32e9 100644 --- a/docs/learn/advanced/12-simulation.md +++ b/docs/learn/advanced/12-simulation.md @@ -7,37 +7,26 @@ sidebar_position: 1 The Cosmos SDK offers a full fledged simulation framework to fuzz test every message defined by a module. -On the Cosmos SDK, this functionality is provided by [`SimApp`](https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/simapp/app_v2.go), which is a -`Baseapp` application that is used for running the [`simulation`](https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/simulation) module. -This module defines all the simulation logic as well as the operations for -randomized parameters like accounts, balances etc. +On the Cosmos SDK, this functionality is provided by [`SimApp`](https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/simapp/app_v2.go), which is a `Baseapp` application that is used for running the [`simulation`](https://github.com/cosmos/cosmos-sdk/blob/23cf89cce1882ba9c8280e64735ae200504bfdce/simsx/README.md#L1) package. This package defines all the simulation logic as well as the operations for randomized parameters like accounts, balances etc. ## Goals -The blockchain simulator tests how the blockchain application would behave under -real life circumstances by generating and sending randomized messages. -The goal of this is to detect and debug failures that could halt a live chain, -by providing logs and statistics about the operations run by the simulator as -well as exporting the latest application state when a failure was found. +The blockchain simulator tests how the blockchain application would behave under real life circumstances by generating and sending randomized messages. The goal of this is to detect and debug failures that could halt a live chain, by providing logs and statistics about the operations run by the simulator as well as exporting the latest application state when a failure was found. -Its main difference with integration testing is that the simulator app allows -you to pass parameters to customize the chain that's being simulated. -This comes in handy when trying to reproduce bugs that were generated in the -provided operations (randomized or not). +Its main difference with integration testing is that the simulator app allows you to pass parameters to customize the chain that's being simulated. This comes in handy when trying to reproduce bugs that were generated in the provided operations (randomized or not). ## Simulation commands The simulation app has different commands, each of which tests a different failure type: -* `AppImportExport`: The simulator exports the initial app state and then it - creates a new app with the exported `genesis.json` as an input, checking for - inconsistencies between the stores. +* `AppImportExport`: The simulator exports the initial app state and then it creates a new app with the exported `genesis.json` as an input, checking for inconsistencies between the stores. * `AppSimulationAfterImport`: Queues two simulations together. The first one provides the app state (_i.e_ genesis) to the second. Useful to test software upgrades or hard-forks from a live chain. * `AppStateDeterminism`: Checks that all the nodes return the same values, in the same order. -* `BenchmarkInvariants`: Analysis of the performance of running all modules' invariants (_i.e_ sequentially runs a [benchmark](https://pkg.go.dev/testing/#hdr-Benchmarks) test). An invariant checks for - differences between the values that are on the store and the passive tracker. Eg: total coins held by accounts vs total supply tracker. +* `BenchmarkInvariants`: Analysis of the performance of running all modules' invariants (_i.e_ sequentially runs a [benchmark](https://pkg.go.dev/testing/#hdr-Benchmarks) test). An invariant checks for differences between the values that are on the store and the passive tracker. Eg: total coins held by accounts vs total supply tracker. * `FullAppSimulation`: General simulation mode. Runs the chain and the specified operations for a given number of blocks. Tests that there're no `panics` on the simulation. It does also run invariant checks on every `Period` but they are not benchmarked. +* `FuzzFullAppSimulation`: Runs general simulation mode with the [go fuzzer](https://go.dev/doc/security/fuzz/) to find panics. +* `AppStateDeterminism`: Runs a few seeds many times to test that the apphash is deterministic across the runs. Each simulation must receive a set of inputs (_i.e_ flags) such as the number of blocks that the simulation is run, seed, block size, etc. @@ -47,23 +36,18 @@ Check the full list of flags [here](https://github.com/cosmos/cosmos-sdk/blob/v0 In addition to the various inputs and commands, the simulator runs in three modes: -1. Completely random where the initial state, module parameters and simulation - parameters are **pseudo-randomly generated**. -2. From a `genesis.json` file where the initial state and the module parameters are defined. - This mode is helpful for running simulations on a known state such as a live network export where a new (mostly likely breaking) version of the application needs to be tested. -3. From a `params.json` file where the initial state is pseudo-randomly generated but the module and simulation parameters can be provided manually. - This allows for a more controlled and deterministic simulation setup while allowing the state space to still be pseudo-randomly simulated. - The list of available parameters are listed [here](https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/simulation/client/cli/flags.go#L59-L78). +1. Completely random where the initial state, module parameters and simulation parameters are **pseudo-randomly generated**. +2. From a `genesis.json` file where the initial state and the module parameters are defined. This mode is helpful for running simulations on a known state such as a live network export where a new (mostly likely breaking) version of the application needs to be tested. +3. From a `params.json` file where the initial state is pseudo-randomly generated but the module and simulation parameters can be provided manually. This allows for a more controlled and deterministic simulation setup while allowing the state space to still be pseudo-randomly simulated. All available parameters are listed [here](https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/simulation/client/cli/flags.go#L59-L78). :::tip -These modes are not mutually exclusive. So you can for example run a randomly -generated genesis state (`1`) with manually generated simulation params (`3`). +These modes are not mutually exclusive. So you can for example run a randomly generated genesis state (`1`) with manually generated simulation params (`3`). ::: ## Usage This is a general example of how simulations are run. For more specific examples -check the Cosmos SDK [Makefile](https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/Makefile#L282-L318). +check the Cosmos SDK [Makefile](https://github.com/cosmos/cosmos-sdk/blob/23cf89cce1882ba9c8280e64735ae200504bfdce/scripts/build/simulations.mk#L1-L104). ```bash $ go test -mod=readonly github.com/cosmos/cosmos-sdk/simapp \ diff --git a/docs/rfc/rfc-006-handlers.md b/docs/rfc/rfc-006-handlers.md index a22992ccdb0c..9770c6774d90 100644 --- a/docs/rfc/rfc-006-handlers.md +++ b/docs/rfc/rfc-006-handlers.md @@ -24,7 +24,7 @@ This has led us to look at a design which would allow the usage of TinyGo and other technologies. We looked at TinyGo for our first target in order to compile down to a 32 bit environment which could be used with -things like [Risc-0](https://www.risczero.com/), [Fluent](https://fluentlabs.xyz/) and other technologies. When speaking with the teams behind these technologies +things like [Risc-0](https://www.risczero.com/), [Fluent](https://fluent.xyz/) and other technologies. When speaking with the teams behind these technologies we found that they were interested in using the Cosmos SDK but were unable to due to being unable to use TinyGo or the Cosmos SDK go code in a 32 bit environment. diff --git a/errors/abci_test.go b/errors/abci_test.go index ca283997ae91..54afb8872600 100644 --- a/errors/abci_test.go +++ b/errors/abci_test.go @@ -102,7 +102,7 @@ func TestABCIInfoSerializeErr(t *testing.T) { }, } for msg, spec := range specs { - spec := spec + _, _, log := ABCIInfo(spec.src, spec.debug) if log != spec.exp { t.Errorf("%s: expected log %s, got %s", msg, spec.exp, log) diff --git a/go.mod b/go.mod index ab8bd9738c9e..c0882266d18b 100644 --- a/go.mod +++ b/go.mod @@ -5,13 +5,13 @@ module github.com/cosmos/cosmos-sdk require ( cosmossdk.io/api v0.7.5 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 - cosmossdk.io/schema v0.2.0 + cosmossdk.io/schema v0.3.0 cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 @@ -44,7 +44,7 @@ require ( github.com/mattn/go-isatty v0.0.20 github.com/mdp/qrterminal/v3 v3.2.0 github.com/muesli/termenv v0.15.2 - github.com/prometheus/client_golang v1.20.3 + github.com/prometheus/client_golang v1.20.4 github.com/prometheus/common v0.59.1 github.com/rs/zerolog v1.33.0 github.com/spf13/cast v1.7.0 diff --git a/go.sum b/go.sum index ca9079b0b3e4..518872d99757 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +14,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -399,8 +399,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/go.work.example b/go.work.example index 834c86da2181..ebc3f15e4f8d 100644 --- a/go.work.example +++ b/go.work.example @@ -26,7 +26,9 @@ use ( ./tools/confix ./tools/hubl ./x/accounts + ./x/accounts/defaults/base ./x/accounts/defaults/lockup + ./x/accounts/defaults/multisig ./x/auth ./x/authz ./x/bank diff --git a/indexer/postgres/create_table_test.go b/indexer/postgres/create_table_test.go index 67851008e40b..ed3f295c120f 100644 --- a/indexer/postgres/create_table_test.go +++ b/indexer/postgres/create_table_test.go @@ -79,11 +79,11 @@ func Example_objectIndexer_createTableSql_vote_no_retain_delete() { // GRANT SELECT ON TABLE "test_vote" TO PUBLIC; } -func exampleCreateTable(objectType schema.ObjectType) { +func exampleCreateTable(objectType schema.StateObjectType) { exampleCreateTableOpt(objectType, false) } -func exampleCreateTableOpt(objectType schema.ObjectType, noRetainDelete bool) { +func exampleCreateTableOpt(objectType schema.StateObjectType, noRetainDelete bool) { tm := newObjectIndexer("test", objectType, options{ logger: logutil.NoopLogger{}, disableRetainDeletions: noRetainDelete, diff --git a/indexer/postgres/go.mod b/indexer/postgres/go.mod index b0423dde0744..c13699a1677a 100644 --- a/indexer/postgres/go.mod +++ b/indexer/postgres/go.mod @@ -8,6 +8,6 @@ go 1.12 // so there are no problems building this with any version of the SDK. // This module should only use the golang standard library (database/sql) // and cosmossdk.io/indexer/base. -require cosmossdk.io/schema v0.1.1 +require cosmossdk.io/schema v0.3.0 replace cosmossdk.io/schema => ../../schema diff --git a/indexer/postgres/internal/testdata/example_schema.go b/indexer/postgres/internal/testdata/example_schema.go index a40d794034b7..45d9aaf8d14a 100644 --- a/indexer/postgres/internal/testdata/example_schema.go +++ b/indexer/postgres/internal/testdata/example_schema.go @@ -4,10 +4,10 @@ import "cosmossdk.io/schema" var ExampleSchema schema.ModuleSchema -var AllKindsObject schema.ObjectType +var AllKindsObject schema.StateObjectType func init() { - AllKindsObject = schema.ObjectType{ + AllKindsObject = schema.StateObjectType{ Name: "all_kinds", KeyFields: []schema.Field{ { @@ -45,7 +45,7 @@ func init() { ) } -var SingletonObject = schema.ObjectType{ +var SingletonObject = schema.StateObjectType{ Name: "singleton", ValueFields: []schema.Field{ { @@ -65,7 +65,7 @@ var SingletonObject = schema.ObjectType{ }, } -var VoteObject = schema.ObjectType{ +var VoteObject = schema.StateObjectType{ Name: "vote", KeyFields: []schema.Field{ { diff --git a/indexer/postgres/module.go b/indexer/postgres/module.go index ffba1a4b2da9..77ae20d88a7c 100644 --- a/indexer/postgres/module.go +++ b/indexer/postgres/module.go @@ -40,7 +40,7 @@ func (m *moduleIndexer) initializeSchema(ctx context.Context, conn dbConn) error } // create tables for all object types - m.schema.ObjectTypes(func(typ schema.ObjectType) bool { + m.schema.StateObjectTypes(func(typ schema.StateObjectType) bool { tm := newObjectIndexer(m.moduleName, typ, m.options) m.tables[typ.Name] = tm err = tm.createTable(ctx, conn) diff --git a/indexer/postgres/object.go b/indexer/postgres/object.go index ce98790a73bb..575fa9c03c25 100644 --- a/indexer/postgres/object.go +++ b/indexer/postgres/object.go @@ -9,14 +9,14 @@ import ( // objectIndexer is a helper struct that generates SQL for a given object type. type objectIndexer struct { moduleName string - typ schema.ObjectType + typ schema.StateObjectType valueFields map[string]schema.Field allFields map[string]schema.Field options options } // newObjectIndexer creates a new objectIndexer for the given object type. -func newObjectIndexer(moduleName string, typ schema.ObjectType, options options) *objectIndexer { +func newObjectIndexer(moduleName string, typ schema.StateObjectType, options options) *objectIndexer { allFields := make(map[string]schema.Field) valueFields := make(map[string]schema.Field) diff --git a/indexer/postgres/select.go b/indexer/postgres/select.go index 03d560a5b76c..242891c1cc75 100644 --- a/indexer/postgres/select.go +++ b/indexer/postgres/select.go @@ -70,11 +70,11 @@ func (tm *objectIndexer) existsSqlAndParams(w io.Writer, key interface{}) ([]int return keyParams, err } -func (tm *objectIndexer) get(ctx context.Context, conn dbConn, key interface{}) (schema.ObjectUpdate, bool, error) { +func (tm *objectIndexer) get(ctx context.Context, conn dbConn, key interface{}) (schema.StateObjectUpdate, bool, error) { buf := new(strings.Builder) params, err := tm.getSqlAndParams(buf, key) if err != nil { - return schema.ObjectUpdate{}, false, err + return schema.StateObjectUpdate{}, false, err } sqlStr := buf.String() @@ -147,7 +147,7 @@ func (tm *objectIndexer) selectAllClause(w io.Writer) error { return nil } -func (tm *objectIndexer) readRow(row interface{ Scan(...interface{}) error }) (schema.ObjectUpdate, bool, error) { +func (tm *objectIndexer) readRow(row interface{ Scan(...interface{}) error }) (schema.StateObjectUpdate, bool, error) { var res []interface{} for _, f := range tm.typ.KeyFields { res = append(res, tm.colBindValue(f)) @@ -164,16 +164,16 @@ func (tm *objectIndexer) readRow(row interface{ Scan(...interface{}) error }) (s err := row.Scan(res...) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return schema.ObjectUpdate{}, false, err + return schema.StateObjectUpdate{}, false, err } - return schema.ObjectUpdate{}, false, err + return schema.StateObjectUpdate{}, false, err } var keys []interface{} for _, field := range tm.typ.KeyFields { x, err := tm.readCol(field, res[0]) if err != nil { - return schema.ObjectUpdate{}, false, err + return schema.StateObjectUpdate{}, false, err } keys = append(keys, x) res = res[1:] @@ -188,7 +188,7 @@ func (tm *objectIndexer) readRow(row interface{ Scan(...interface{}) error }) (s for _, field := range tm.typ.ValueFields { x, err := tm.readCol(field, res[0]) if err != nil { - return schema.ObjectUpdate{}, false, err + return schema.StateObjectUpdate{}, false, err } values = append(values, x) res = res[1:] @@ -199,7 +199,7 @@ func (tm *objectIndexer) readRow(row interface{ Scan(...interface{}) error }) (s value = values[0] } - update := schema.ObjectUpdate{ + update := schema.StateObjectUpdate{ TypeName: tm.typ.Name, Key: key, Value: value, diff --git a/indexer/postgres/tests/go.mod b/indexer/postgres/tests/go.mod index c7a0c1e535fb..b02fb01dd8aa 100644 --- a/indexer/postgres/tests/go.mod +++ b/indexer/postgres/tests/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( cosmossdk.io/indexer/postgres v0.0.0-00010101000000-000000000000 - cosmossdk.io/schema v0.1.1 + cosmossdk.io/schema v0.3.0 cosmossdk.io/schema/testing v0.0.0 github.com/fergusstrange/embedded-postgres v1.29.0 github.com/hashicorp/consul/sdk v0.16.1 diff --git a/indexer/postgres/view.go b/indexer/postgres/view.go index eac2c52f8a8b..1669e251da8a 100644 --- a/indexer/postgres/view.go +++ b/indexer/postgres/view.go @@ -100,15 +100,15 @@ type objectView struct { conn dbConn } -func (tm *objectView) ObjectType() schema.ObjectType { +func (tm *objectView) ObjectType() schema.StateObjectType { return tm.typ } -func (tm *objectView) GetObject(key interface{}) (update schema.ObjectUpdate, found bool, err error) { +func (tm *objectView) GetObject(key interface{}) (update schema.StateObjectUpdate, found bool, err error) { return tm.get(tm.ctx, tm.conn, key) } -func (tm *objectView) AllState(f func(schema.ObjectUpdate, error) bool) { +func (tm *objectView) AllState(f func(schema.StateObjectUpdate, error) bool) { buf := new(strings.Builder) err := tm.selectAllSql(buf) if err != nil { diff --git a/math/dec_internal_test.go b/math/dec_internal_test.go index 8b899300e3b0..5273edfc9b5e 100644 --- a/math/dec_internal_test.go +++ b/math/dec_internal_test.go @@ -90,7 +90,6 @@ func (s *decimalInternalTestSuite) TestDecMarshalJSON() { {"12340Int", LegacyNewDec(12340), "\"12340.000000000000000000\"", false}, } for _, tt := range tests { - tt := tt s.T().Run(tt.name, func(t *testing.T) { got, err := tt.d.MarshalJSON() if (err != nil) != tt.wantErr { diff --git a/math/dec_test.go b/math/dec_test.go index 1e72e173e84f..e8336a97a24c 100644 --- a/math/dec_test.go +++ b/math/dec_test.go @@ -261,7 +261,7 @@ func (s *decimalTestSuite) TestArithmetic() { } for tcIndex, tc := range tests { - tc := tc + resAdd := tc.d1.Add(tc.d2) resSub := tc.d1.Sub(tc.d2) resMul := tc.d1.Mul(tc.d2) @@ -727,7 +727,6 @@ func TestFormatDec(t *testing.T) { require.NoError(t, err) for _, tc := range testcases { - tc := tc t.Run(tc[0], func(t *testing.T) { out, err := math.FormatDec(tc[0]) require.NoError(t, err) @@ -1026,3 +1025,36 @@ func TestQuoMut(t *testing.T) { }) } } + +func Test_DocumentLegacyAsymmetry(t *testing.T) { + zeroDec := math.LegacyZeroDec() + emptyDec := math.LegacyDec{} + + zeroDecBz, err := zeroDec.Marshal() + require.NoError(t, err) + zeroDecJSON := zeroDec.String() + + emptyDecBz, err := emptyDec.Marshal() + require.NoError(t, err) + emptyDecJSON := emptyDec.String() + + // makes sense, zero and empty are semantically different and render differently + require.NotEqual(t, zeroDecJSON, emptyDecJSON) + // but on the proto wire they encode to the same bytes + require.Equal(t, zeroDecBz, emptyDecBz) + + // zero values are symmetrical + zeroDecRoundTrip := math.LegacyDec{} + err = zeroDecRoundTrip.Unmarshal(zeroDecBz) + require.NoError(t, err) + require.Equal(t, zeroDec.String(), zeroDecRoundTrip.String()) + require.Equal(t, zeroDec, zeroDecRoundTrip) + + // empty values are not + emptyDecRoundTrip := math.LegacyDec{} + err = emptyDecRoundTrip.Unmarshal(emptyDecBz) + require.NoError(t, err) + // !!! this is the key point, they are not equal, it looks like a bug + require.NotEqual(t, emptyDec.String(), emptyDecRoundTrip.String()) + require.NotEqual(t, emptyDec, emptyDecRoundTrip) +} diff --git a/math/int_test.go b/math/int_test.go index 714ef5e65e50..36c2e453ea06 100644 --- a/math/int_test.go +++ b/math/int_test.go @@ -591,7 +591,6 @@ func TestFormatIntCorrectness(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.in, func(t *testing.T) { got, err := math.FormatInt(tt.in) if err != nil { diff --git a/math/uint_test.go b/math/uint_test.go index 93abdf886dae..b02b442159b3 100644 --- a/math/uint_test.go +++ b/math/uint_test.go @@ -244,7 +244,7 @@ func (s *uintTestSuite) TestSafeSub() { } for i, tc := range testCases { - tc := tc + if tc.panic { s.Require().Panics(func() { tc.x.Sub(tc.y) }) continue diff --git a/orm/encoding/ormfield/duration_test.go b/orm/encoding/ormfield/duration_test.go index 485605ee0c1b..6f612ef1a1aa 100644 --- a/orm/encoding/ormfield/duration_test.go +++ b/orm/encoding/ormfield/duration_test.go @@ -140,7 +140,6 @@ func TestDurationOutOfRange(t *testing.T) { }, } for _, tc := range tt { - tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() val := protoreflect.ValueOfMessage(tc.dur.ProtoReflect()) @@ -272,7 +271,6 @@ func TestDurationCompare(t *testing.T) { } for _, tc := range tt { - tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() diff --git a/orm/encoding/ormfield/timestamp_test.go b/orm/encoding/ormfield/timestamp_test.go index 52b7caeadacd..401e940b2762 100644 --- a/orm/encoding/ormfield/timestamp_test.go +++ b/orm/encoding/ormfield/timestamp_test.go @@ -114,7 +114,6 @@ func TestTimestampOutOfRange(t *testing.T) { }, } for _, tc := range tt { - tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() val := protoreflect.ValueOfMessage(tc.ts.ProtoReflect()) diff --git a/orm/go.mod b/orm/go.mod index bbaab608c46f..f0f1c88ca203 100644 --- a/orm/go.mod +++ b/orm/go.mod @@ -51,7 +51,7 @@ require ( github.com/onsi/gomega v1.20.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/orm/go.sum b/orm/go.sum index 986912fd8e4e..b098773210a8 100644 --- a/orm/go.sum +++ b/orm/go.sum @@ -133,8 +133,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= diff --git a/runtime/app.go b/runtime/app.go index f9a74a29a208..e63da54c0e12 100644 --- a/runtime/app.go +++ b/runtime/app.go @@ -6,6 +6,8 @@ import ( "slices" abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" + cmtcrypto "github.com/cometbft/cometbft/crypto" + cmted25519 "github.com/cometbft/cometbft/crypto/ed25519" "google.golang.org/grpc" runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1" @@ -30,6 +32,9 @@ import ( authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" ) +// KeyGenF is a function that generates a private key for use by comet. +type KeyGenF = func() (cmtcrypto.PrivKey, error) + // App is a wrapper around BaseApp and ModuleManager that can be used in hybrid // app.go/app config scenarios or directly as a servertypes.Application instance. // To get an instance of *App, *AppBuilder must be requested as a dependency @@ -45,7 +50,7 @@ type App struct { ModuleManager *module.Manager UnorderedTxManager *unorderedtx.Manager - configurator module.Configurator // nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. + configurator module.Configurator //nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. config *runtimev1alpha1.Module storeKeys []storetypes.StoreKey interfaceRegistry codectypes.InterfaceRegistry @@ -251,7 +256,7 @@ func (a *App) RegisterNodeService(clientCtx client.Context, cfg config.Config) { } // Configurator returns the app's configurator. -func (a *App) Configurator() module.Configurator { // nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. +func (a *App) Configurator() module.Configurator { //nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. return a.configurator } @@ -308,3 +313,10 @@ var _ servertypes.Application = &App{} type hasServicesV1 interface { RegisterServices(grpc.ServiceRegistrar) error } + +// ValidatorKeyProvider returns a function that generates a private key for use by comet. +func (a *App) ValidatorKeyProvider() KeyGenF { + return func() (cmtcrypto.PrivKey, error) { + return cmted25519.GenPrivKey(), nil + } +} diff --git a/runtime/builder.go b/runtime/builder.go index 68b58b66a000..37be02fa769e 100644 --- a/runtime/builder.go +++ b/runtime/builder.go @@ -39,9 +39,18 @@ func (a *AppBuilder) Build(db corestore.KVStoreWithBatch, traceStore io.Writer, baseAppOptions = append(baseAppOptions, option) } + // set routers first in case they get modified by other options + baseAppOptions = append( + []func(*baseapp.BaseApp){ + func(bApp *baseapp.BaseApp) { + bApp.SetMsgServiceRouter(a.app.msgServiceRouter) + bApp.SetGRPCQueryRouter(a.app.grpcQueryRouter) + }, + }, + baseAppOptions..., + ) + bApp := baseapp.NewBaseApp(a.app.config.AppName, a.app.logger, db, nil, baseAppOptions...) - bApp.SetMsgServiceRouter(a.app.msgServiceRouter) - bApp.SetGRPCQueryRouter(a.app.grpcQueryRouter) bApp.SetCommitMultiStoreTracer(traceStore) bApp.SetVersion(version.Version) bApp.SetInterfaceRegistry(a.app.interfaceRegistry) diff --git a/runtime/module.go b/runtime/module.go index 95595fc209f8..773efe10a3e2 100644 --- a/runtime/module.go +++ b/runtime/module.go @@ -39,7 +39,7 @@ type appModule struct { func (m appModule) IsOnePerModuleType() {} func (m appModule) IsAppModule() {} -func (m appModule) RegisterServices(configurator module.Configurator) { // nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. +func (m appModule) RegisterServices(configurator module.Configurator) { //nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. err := m.app.registerRuntimeServices(configurator) if err != nil { panic(err) diff --git a/runtime/services.go b/runtime/services.go index 2f453898ff88..c36f7e3e0331 100644 --- a/runtime/services.go +++ b/runtime/services.go @@ -8,7 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" ) -func (a *App) registerRuntimeServices(cfg module.Configurator) error { // nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. +func (a *App) registerRuntimeServices(cfg module.Configurator) error { //nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. autocliv1.RegisterQueryServer(cfg.QueryServer(), services.NewAutoCLIQueryService(a.ModuleManager.Modules)) reflectionSvc, err := services.NewReflectionService() diff --git a/runtime/services/autocli.go b/runtime/services/autocli.go index c6b66e510d62..cd2005690d1e 100644 --- a/runtime/services/autocli.go +++ b/runtime/services/autocli.go @@ -105,7 +105,7 @@ type autocliConfigurator struct { err error } -var _ module.Configurator = &autocliConfigurator{} // nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. +var _ module.Configurator = &autocliConfigurator{} //nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. func (a *autocliConfigurator) MsgServer() gogogrpc.Server { return &a.msgServer } diff --git a/runtime/store.go b/runtime/store.go index a6a2866fbeb3..df2a40f06b0c 100644 --- a/runtime/store.go +++ b/runtime/store.go @@ -2,6 +2,8 @@ package runtime import ( "context" + "errors" + "fmt" "io" "cosmossdk.io/core/store" @@ -184,6 +186,11 @@ func KVStoreAdapter(store store.KVStore) storetypes.KVStore { // UpgradeStoreLoader is used to prepare baseapp with a fixed StoreLoader // pattern. This is useful for custom upgrade loading logic. func UpgradeStoreLoader(upgradeHeight int64, storeUpgrades *store.StoreUpgrades) baseapp.StoreLoader { + // sanity checks on store upgrades + if err := checkStoreUpgrade(storeUpgrades); err != nil { + panic(err) + } + return func(ms storetypes.CommitMultiStore) error { if upgradeHeight == ms.LastCommitID().Version+1 { // Check if the current commit version and upgrade height matches @@ -200,3 +207,40 @@ func UpgradeStoreLoader(upgradeHeight int64, storeUpgrades *store.StoreUpgrades) return baseapp.DefaultStoreLoader(ms) } } + +// checkStoreUpgrade performs sanity checks on the store upgrades +func checkStoreUpgrade(storeUpgrades *store.StoreUpgrades) error { + if storeUpgrades == nil { + return errors.New("store upgrades cannot be nil") + } + + // check for duplicates + addedFilter := make(map[string]struct{}) + deletedFilter := make(map[string]struct{}) + + for _, key := range storeUpgrades.Added { + if _, ok := addedFilter[key]; ok { + return fmt.Errorf("store upgrade has duplicate key %s in added", key) + } + addedFilter[key] = struct{}{} + } + for _, key := range storeUpgrades.Deleted { + if _, ok := deletedFilter[key]; ok { + return fmt.Errorf("store upgrade has duplicate key %s in deleted", key) + } + deletedFilter[key] = struct{}{} + } + + for _, key := range storeUpgrades.Added { + if _, ok := deletedFilter[key]; ok { + return fmt.Errorf("store upgrade has key %s in both added and deleted", key) + } + } + for _, key := range storeUpgrades.Deleted { + if _, ok := addedFilter[key]; ok { + return fmt.Errorf("store upgrade has key %s in both added and deleted", key) + } + } + + return nil +} diff --git a/runtime/store_test.go b/runtime/store_test.go new file mode 100644 index 000000000000..a583a08d0391 --- /dev/null +++ b/runtime/store_test.go @@ -0,0 +1,65 @@ +package runtime + +import ( + "testing" + + "github.com/stretchr/testify/require" + + corestore "cosmossdk.io/core/store" +) + +func TestCheckStoreUpgrade(t *testing.T) { + tests := []struct { + name string + storeUpgrades *corestore.StoreUpgrades + errMsg string + }{ + { + name: "Nil StoreUpgrades", + storeUpgrades: nil, + errMsg: "store upgrades cannot be nil", + }, + { + name: "Valid StoreUpgrades", + storeUpgrades: &corestore.StoreUpgrades{ + Added: []string{"store1", "store2"}, + Deleted: []string{"store3", "store4"}, + }, + }, + { + name: "Duplicate key in Added", + storeUpgrades: &corestore.StoreUpgrades{ + Added: []string{"store1", "store2", "store1"}, + Deleted: []string{"store3"}, + }, + errMsg: "store upgrade has duplicate key store1 in added", + }, + { + name: "Duplicate key in Deleted", + storeUpgrades: &corestore.StoreUpgrades{ + Added: []string{"store1"}, + Deleted: []string{"store2", "store3", "store2"}, + }, + errMsg: "store upgrade has duplicate key store2 in deleted", + }, + { + name: "Key in both Added and Deleted", + storeUpgrades: &corestore.StoreUpgrades{ + Added: []string{"store1", "store2"}, + Deleted: []string{"store2", "store3"}, + }, + errMsg: "store upgrade has key store2 in both added and deleted", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := checkStoreUpgrade(tt.storeUpgrades) + if tt.errMsg == "" { + require.NoError(t, err) + } else { + require.ErrorContains(t, err, tt.errMsg) + } + }) + } +} diff --git a/runtime/v2/go.mod b/runtime/v2/go.mod index 4327d9d1c3e9..078344e65088 100644 --- a/runtime/v2/go.mod +++ b/runtime/v2/go.mod @@ -14,7 +14,7 @@ replace ( require ( cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/depinject v1.0.0 cosmossdk.io/log v1.4.1 cosmossdk.io/server/v2/appmanager v0.0.0-00010101000000-000000000000 @@ -31,6 +31,7 @@ require ( buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 // indirect + cosmossdk.io/schema v0.3.0 // indirect github.com/DataDog/zstd v1.5.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -63,7 +64,7 @@ require ( github.com/onsi/gomega v1.28.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/runtime/v2/go.sum b/runtime/v2/go.sum index 30d27ab50056..e00a3c9f8791 100644 --- a/runtime/v2/go.sum +++ b/runtime/v2/go.sum @@ -2,14 +2,16 @@ buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fed buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2/go.mod h1:1+3gJj2NvZ1mTLAtHu+lMhOjGgQPiCKCeo+9MBww0Eo= buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 h1:b7EEYTUHmWSBEyISHlHvXbJPqtKiHRuUignL1tsHnNQ= buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 h1:IQNdY2kB+k+1OM2DvqFG1+UgeU1JzZrWtwuWzI3ZfwA= cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5/go.mod h1:0CuYKkFHxc1vw2JC+t21THBCALJVROrWVR/3PQ1urpc= cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= @@ -189,8 +191,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/runtime/v2/manager.go b/runtime/v2/manager.go index b748a707d118..d2213a7b86e5 100644 --- a/runtime/v2/manager.go +++ b/runtime/v2/manager.go @@ -575,7 +575,6 @@ func (m *MM[T]) assertNoForgottenModules( } var missing []string for m := range m.modules { - m := m if pass != nil && pass(m) { continue } diff --git a/runtime/v2/store.go b/runtime/v2/store.go index 5268033ad323..40912ea41f48 100644 --- a/runtime/v2/store.go +++ b/runtime/v2/store.go @@ -1,6 +1,7 @@ package runtime import ( + "errors" "fmt" "cosmossdk.io/core/store" @@ -69,6 +70,11 @@ func DefaultStoreLoader(store Store) error { // UpgradeStoreLoader upgrades the store if the upgrade height matches the current version, it is used as a replacement // for the DefaultStoreLoader when there are store upgrades func UpgradeStoreLoader(upgradeHeight int64, storeUpgrades *store.StoreUpgrades) StoreLoader { + // sanity checks on store upgrades + if err := checkStoreUpgrade(storeUpgrades); err != nil { + panic(err) + } + return func(store Store) error { latestVersion, err := store.GetLatestVersion() if err != nil { @@ -88,3 +94,40 @@ func UpgradeStoreLoader(upgradeHeight int64, storeUpgrades *store.StoreUpgrades) return DefaultStoreLoader(store) } } + +// checkStoreUpgrade performs sanity checks on the store upgrades +func checkStoreUpgrade(storeUpgrades *store.StoreUpgrades) error { + if storeUpgrades == nil { + return errors.New("store upgrades cannot be nil") + } + + // check for duplicates + addedFilter := make(map[string]struct{}) + deletedFilter := make(map[string]struct{}) + + for _, key := range storeUpgrades.Added { + if _, ok := addedFilter[key]; ok { + return fmt.Errorf("store upgrade has duplicate key %s in added", key) + } + addedFilter[key] = struct{}{} + } + for _, key := range storeUpgrades.Deleted { + if _, ok := deletedFilter[key]; ok { + return fmt.Errorf("store upgrade has duplicate key %s in deleted", key) + } + deletedFilter[key] = struct{}{} + } + + for _, key := range storeUpgrades.Added { + if _, ok := deletedFilter[key]; ok { + return fmt.Errorf("store upgrade has key %s in both added and deleted", key) + } + } + for _, key := range storeUpgrades.Deleted { + if _, ok := addedFilter[key]; ok { + return fmt.Errorf("store upgrade has key %s in both added and deleted", key) + } + } + + return nil +} diff --git a/runtime/v2/store_test.go b/runtime/v2/store_test.go new file mode 100644 index 000000000000..64ad7e9cc274 --- /dev/null +++ b/runtime/v2/store_test.go @@ -0,0 +1,71 @@ +package runtime + +import ( + "testing" + + corestore "cosmossdk.io/core/store" +) + +func TestCheckStoreUpgrade(t *testing.T) { + tests := []struct { + name string + storeUpgrades *corestore.StoreUpgrades + wantErr bool + errMsg string + }{ + { + name: "Nil StoreUpgrades", + storeUpgrades: nil, + wantErr: true, + errMsg: "store upgrades cannot be nil", + }, + { + name: "Valid StoreUpgrades", + storeUpgrades: &corestore.StoreUpgrades{ + Added: []string{"store1", "store2"}, + Deleted: []string{"store3", "store4"}, + }, + wantErr: false, + }, + { + name: "Duplicate key in Added", + storeUpgrades: &corestore.StoreUpgrades{ + Added: []string{"store1", "store2", "store1"}, + Deleted: []string{"store3"}, + }, + wantErr: true, + errMsg: "store upgrade has duplicate key store1 in added", + }, + { + name: "Duplicate key in Deleted", + storeUpgrades: &corestore.StoreUpgrades{ + Added: []string{"store1"}, + Deleted: []string{"store2", "store3", "store2"}, + }, + wantErr: true, + errMsg: "store upgrade has duplicate key store2 in deleted", + }, + { + name: "Key in both Added and Deleted", + storeUpgrades: &corestore.StoreUpgrades{ + Added: []string{"store1", "store2"}, + Deleted: []string{"store2", "store3"}, + }, + wantErr: true, + errMsg: "store upgrade has key store2 in both added and deleted", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := checkStoreUpgrade(tt.storeUpgrades) + if (err != nil) != tt.wantErr { + t.Errorf("checkStoreUpgrade() error = %v, wantErr %v", err, tt.wantErr) + return + } + if err != nil && err.Error() != tt.errMsg { + t.Errorf("checkStoreUpgrade() error message = %v, want %v", err.Error(), tt.errMsg) + } + }) + } +} diff --git a/schema/appdata/data.go b/schema/appdata/data.go index ef54fd2553ae..9b8ecc058565 100644 --- a/schema/appdata/data.go +++ b/schema/appdata/data.go @@ -131,7 +131,7 @@ type ObjectUpdateData struct { ModuleName string // Updates are the object updates. - Updates []schema.ObjectUpdate + Updates []schema.StateObjectUpdate } // CommitData represents commit data. It is empty for now, but fields could be added later. diff --git a/schema/appdata/mux.go b/schema/appdata/mux.go index 81a4fa795db8..1eab8b69a6fe 100644 --- a/schema/appdata/mux.go +++ b/schema/appdata/mux.go @@ -139,7 +139,7 @@ func ListenerMux(listeners ...Listener) Listener { mux.onBatch = func(batch PacketBatch) error { for _, listener := range listeners { - err := batch.apply(&listener) + err := batch.apply(&listener) //nolint:gosec // aliasing is safe here if err != nil { return err } diff --git a/schema/decoder.go b/schema/decoder.go index fcebbf3d7ba8..e0fecf2a36b7 100644 --- a/schema/decoder.go +++ b/schema/decoder.go @@ -13,18 +13,18 @@ type ModuleCodec struct { // Schema is the schema for the module. It is required. Schema ModuleSchema - // KVDecoder is a function that decodes a key-value pair into an ObjectUpdate. + // KVDecoder is a function that decodes a key-value pair into an StateObjectUpdate. // If it is nil, the module doesn't support state decoding directly. KVDecoder KVDecoder } -// KVDecoder is a function that decodes a key-value pair into one or more ObjectUpdate's. +// KVDecoder is a function that decodes a key-value pair into one or more StateObjectUpdate's. // If the KV-pair doesn't represent object updates, the function should return nil as the first // and no error. The error result should only be non-nil when the decoder expected // to parse a valid update and was unable to. In the case of an error, the decoder may return // a non-nil value for the first return value, which can indicate which parts of the update // were decodable to aid debugging. -type KVDecoder = func(KVPairUpdate) ([]ObjectUpdate, error) +type KVDecoder = func(KVPairUpdate) ([]StateObjectUpdate, error) // KVPairUpdate represents a key-value pair set or delete. type KVPairUpdate = struct { diff --git a/schema/decoding/decoding_test.go b/schema/decoding/decoding_test.go index 7e1a08c92b7c..f69023757c9e 100644 --- a/schema/decoding/decoding_test.go +++ b/schema/decoding/decoding_test.go @@ -29,7 +29,7 @@ func TestMiddleware(t *testing.T) { tl.oneMod.SetValue("abc") - expectedBank := []schema.ObjectUpdate{ + expectedBank := []schema.StateObjectUpdate{ { TypeName: "supply", Key: []interface{}{"foo"}, @@ -56,7 +56,7 @@ func TestMiddleware(t *testing.T) { t.Fatalf("expected %v, got %v", expectedBank, tl.bankUpdates) } - expectedOne := []schema.ObjectUpdate{ + expectedOne := []schema.StateObjectUpdate{ {TypeName: "item", Value: "abc"}, } @@ -84,7 +84,7 @@ func TestMiddleware_filtered(t *testing.T) { t.Fatalf("expected no bank updates") } - expectedOne := []schema.ObjectUpdate{ + expectedOne := []schema.StateObjectUpdate{ {TypeName: "item", Value: "abc"}, } @@ -108,7 +108,7 @@ func TestSync(t *testing.T) { t.Fatal("unexpected error", err) } - expected := []schema.ObjectUpdate{ + expected := []schema.StateObjectUpdate{ { TypeName: "balances", Key: []interface{}{"alice", "foo"}, @@ -130,7 +130,7 @@ func TestSync(t *testing.T) { t.Fatalf("expected %v, got %v", expected, tl.bankUpdates) } - expectedOne := []schema.ObjectUpdate{ + expectedOne := []schema.StateObjectUpdate{ {TypeName: "item", Value: "def"}, } @@ -157,7 +157,7 @@ func TestSync_filtered(t *testing.T) { t.Fatalf("expected no bank updates") } - expectedOne := []schema.ObjectUpdate{ + expectedOne := []schema.StateObjectUpdate{ {TypeName: "item", Value: "def"}, } @@ -168,8 +168,8 @@ func TestSync_filtered(t *testing.T) { type testFixture struct { appdata.Listener - bankUpdates []schema.ObjectUpdate - oneValueUpdates []schema.ObjectUpdate + bankUpdates []schema.StateObjectUpdate + oneValueUpdates []schema.StateObjectUpdate resolver DecoderResolver multiStore *testMultiStore bankMod *exampleBankModule @@ -371,7 +371,7 @@ func (e exampleBankModule) subBalance(acct, denom string, amount uint64) error { func init() { var err error - exampleBankSchema, err = schema.CompileModuleSchema(schema.ObjectType{ + exampleBankSchema, err = schema.CompileModuleSchema(schema.StateObjectType{ Name: "balances", KeyFields: []schema.Field{ { @@ -400,7 +400,7 @@ var exampleBankSchema schema.ModuleSchema func (e exampleBankModule) ModuleCodec() (schema.ModuleCodec, error) { return schema.ModuleCodec{ Schema: exampleBankSchema, - KVDecoder: func(update schema.KVPairUpdate) ([]schema.ObjectUpdate, error) { + KVDecoder: func(update schema.KVPairUpdate) ([]schema.StateObjectUpdate, error) { key := string(update.Key) value, err := strconv.ParseUint(string(update.Value), 10, 64) if err != nil { @@ -408,14 +408,14 @@ func (e exampleBankModule) ModuleCodec() (schema.ModuleCodec, error) { } if strings.HasPrefix(key, "balance/") { parts := strings.Split(key, "/") - return []schema.ObjectUpdate{{ + return []schema.StateObjectUpdate{{ TypeName: "balances", Key: []interface{}{parts[1], parts[2]}, Value: value, }}, nil } else if strings.HasPrefix(key, "supply/") { parts := strings.Split(key, "/") - return []schema.ObjectUpdate{{ + return []schema.StateObjectUpdate{{ TypeName: "supply", Key: []interface{}{parts[1]}, Value: value, @@ -435,7 +435,7 @@ type oneValueModule struct { func init() { var err error - oneValueModSchema, err = schema.CompileModuleSchema(schema.ObjectType{ + oneValueModSchema, err = schema.CompileModuleSchema(schema.StateObjectType{ Name: "item", ValueFields: []schema.Field{ {Name: "value", Kind: schema.StringKind}, @@ -451,11 +451,11 @@ var oneValueModSchema schema.ModuleSchema func (i oneValueModule) ModuleCodec() (schema.ModuleCodec, error) { return schema.ModuleCodec{ Schema: oneValueModSchema, - KVDecoder: func(update schema.KVPairUpdate) ([]schema.ObjectUpdate, error) { + KVDecoder: func(update schema.KVPairUpdate) ([]schema.StateObjectUpdate, error) { if string(update.Key) != "key" { return nil, fmt.Errorf("unexpected key: %v", update.Key) } - return []schema.ObjectUpdate{ + return []schema.StateObjectUpdate{ {TypeName: "item", Value: string(update.Value)}, }, nil }, diff --git a/schema/decoding/resolver_test.go b/schema/decoding/resolver_test.go index 397b97bd6c33..e3a98863681a 100644 --- a/schema/decoding/resolver_test.go +++ b/schema/decoding/resolver_test.go @@ -10,7 +10,7 @@ import ( type modA struct{} func (m modA) ModuleCodec() (schema.ModuleCodec, error) { - modSchema, err := schema.CompileModuleSchema(schema.ObjectType{Name: "A", KeyFields: []schema.Field{{Name: "field1", Kind: schema.StringKind}}}) + modSchema, err := schema.CompileModuleSchema(schema.StateObjectType{Name: "A", KeyFields: []schema.Field{{Name: "field1", Kind: schema.StringKind}}}) if err != nil { return schema.ModuleCodec{}, err } @@ -22,7 +22,7 @@ func (m modA) ModuleCodec() (schema.ModuleCodec, error) { type modB struct{} func (m modB) ModuleCodec() (schema.ModuleCodec, error) { - modSchema, err := schema.CompileModuleSchema(schema.ObjectType{Name: "B", KeyFields: []schema.Field{{Name: "field2", Kind: schema.StringKind}}}) + modSchema, err := schema.CompileModuleSchema(schema.StateObjectType{Name: "B", KeyFields: []schema.Field{{Name: "field2", Kind: schema.StringKind}}}) if err != nil { return schema.ModuleCodec{}, err } @@ -45,7 +45,7 @@ func TestModuleSetDecoderResolver_IterateAll(t *testing.T) { objectTypes := map[string]bool{} err := testResolver.IterateAll(func(moduleName string, cdc schema.ModuleCodec) error { cdc.Schema.AllTypes(func(t schema.Type) bool { - objTyp, ok := t.(schema.ObjectType) + objTyp, ok := t.(schema.StateObjectType) if ok { objectTypes[objTyp.Name] = true } diff --git a/schema/diff/diff.go b/schema/diff/diff.go index 9626ac1cf200..f521e7cb7a7b 100644 --- a/schema/diff/diff.go +++ b/schema/diff/diff.go @@ -4,14 +4,14 @@ import "cosmossdk.io/schema" // ModuleSchemaDiff represents the difference between two module schemas. type ModuleSchemaDiff struct { - // AddedObjectTypes is a list of object types that were added. - AddedObjectTypes []schema.ObjectType + // AddedStateObjectTypes is a list of object types that were added. + AddedStateObjectTypes []schema.StateObjectType - // ChangedObjectTypes is a list of object types that were changed. - ChangedObjectTypes []ObjectTypeDiff + // ChangedStateObjectTypes is a list of object types that were changed. + ChangedStateObjectTypes []StateObjectTypeDiff - // RemovedObjectTypes is a list of object types that were removed. - RemovedObjectTypes []schema.ObjectType + // RemovedStateObjectTypes is a list of object types that were removed. + RemovedStateObjectTypes []schema.StateObjectType // AddedEnumTypes is a list of enum types that were added. AddedEnumTypes []schema.EnumType @@ -41,23 +41,23 @@ type ModuleSchemaDiff struct { func CompareModuleSchemas(oldSchema, newSchema schema.ModuleSchema) ModuleSchemaDiff { diff := ModuleSchemaDiff{} - oldSchema.ObjectTypes(func(oldObj schema.ObjectType) bool { - newObj, found := newSchema.LookupObjectType(oldObj.Name) + oldSchema.StateObjectTypes(func(oldObj schema.StateObjectType) bool { + newObj, found := newSchema.LookupStateObjectType(oldObj.Name) if !found { - diff.RemovedObjectTypes = append(diff.RemovedObjectTypes, oldObj) + diff.RemovedStateObjectTypes = append(diff.RemovedStateObjectTypes, oldObj) return true } objDiff := compareObjectType(oldObj, newObj) if !objDiff.Empty() { - diff.ChangedObjectTypes = append(diff.ChangedObjectTypes, objDiff) + diff.ChangedStateObjectTypes = append(diff.ChangedStateObjectTypes, objDiff) } return true }) - newSchema.ObjectTypes(func(newObj schema.ObjectType) bool { - _, found := oldSchema.LookupObjectType(newObj.TypeName()) + newSchema.StateObjectTypes(func(newObj schema.StateObjectType) bool { + _, found := oldSchema.LookupStateObjectType(newObj.TypeName()) if !found { - diff.AddedObjectTypes = append(diff.AddedObjectTypes, newObj) + diff.AddedStateObjectTypes = append(diff.AddedStateObjectTypes, newObj) } return true }) @@ -87,9 +87,9 @@ func CompareModuleSchemas(oldSchema, newSchema schema.ModuleSchema) ModuleSchema } func (m ModuleSchemaDiff) Empty() bool { - return len(m.AddedObjectTypes) == 0 && - len(m.ChangedObjectTypes) == 0 && - len(m.RemovedObjectTypes) == 0 && + return len(m.AddedStateObjectTypes) == 0 && + len(m.ChangedStateObjectTypes) == 0 && + len(m.RemovedStateObjectTypes) == 0 && len(m.AddedEnumTypes) == 0 && len(m.ChangedEnumTypes) == 0 && len(m.RemovedEnumTypes) == 0 @@ -102,11 +102,11 @@ func (m ModuleSchemaDiff) Empty() bool { func (m ModuleSchemaDiff) HasCompatibleChanges() bool { // object and enum types can be added but not removed // changed object and enum types must have compatible changes - if len(m.RemovedObjectTypes) != 0 || len(m.RemovedEnumTypes) != 0 { + if len(m.RemovedStateObjectTypes) != 0 || len(m.RemovedEnumTypes) != 0 { return false } - for _, objectType := range m.ChangedObjectTypes { + for _, objectType := range m.ChangedStateObjectTypes { if !objectType.HasCompatibleChanges() { return false } diff --git a/schema/diff/diff_test.go b/schema/diff/diff_test.go index c193cbe01ba1..6b12c6c2e6cb 100644 --- a/schema/diff/diff_test.go +++ b/schema/diff/diff_test.go @@ -18,11 +18,11 @@ func TestCompareModuleSchemas(t *testing.T) { }{ { name: "no change", - oldSchema: requireModuleSchema(t, schema.ObjectType{ + oldSchema: requireModuleSchema(t, schema.StateObjectType{ Name: "object1", KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}}, }), - newSchema: requireModuleSchema(t, schema.ObjectType{ + newSchema: requireModuleSchema(t, schema.StateObjectType{ Name: "object1", KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}}, }), @@ -33,12 +33,12 @@ func TestCompareModuleSchemas(t *testing.T) { { name: "object type added", oldSchema: requireModuleSchema(t), - newSchema: requireModuleSchema(t, schema.ObjectType{ + newSchema: requireModuleSchema(t, schema.StateObjectType{ Name: "object1", KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}}, }), diff: ModuleSchemaDiff{ - AddedObjectTypes: []schema.ObjectType{ + AddedStateObjectTypes: []schema.StateObjectType{ { Name: "object1", KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}}, @@ -49,13 +49,13 @@ func TestCompareModuleSchemas(t *testing.T) { }, { name: "object type removed", - oldSchema: requireModuleSchema(t, schema.ObjectType{ + oldSchema: requireModuleSchema(t, schema.StateObjectType{ Name: "object1", KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}}, }), newSchema: requireModuleSchema(t), diff: ModuleSchemaDiff{ - RemovedObjectTypes: []schema.ObjectType{ + RemovedStateObjectTypes: []schema.StateObjectType{ { Name: "object1", KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}}, @@ -66,16 +66,16 @@ func TestCompareModuleSchemas(t *testing.T) { }, { name: "object type changed, key field added", - oldSchema: requireModuleSchema(t, schema.ObjectType{ + oldSchema: requireModuleSchema(t, schema.StateObjectType{ Name: "object1", KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}}, }), - newSchema: requireModuleSchema(t, schema.ObjectType{ + newSchema: requireModuleSchema(t, schema.StateObjectType{ Name: "object1", KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}, {Name: "key2", Kind: schema.StringKind}}, }), diff: ModuleSchemaDiff{ - ChangedObjectTypes: []ObjectTypeDiff{ + ChangedStateObjectTypes: []StateObjectTypeDiff{ { Name: "object1", KeyFieldsDiff: FieldsDiff{ @@ -90,17 +90,17 @@ func TestCompareModuleSchemas(t *testing.T) { }, { name: "object type changed, nullable value field added", - oldSchema: requireModuleSchema(t, schema.ObjectType{ + oldSchema: requireModuleSchema(t, schema.StateObjectType{ Name: "object1", KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}}, }), - newSchema: requireModuleSchema(t, schema.ObjectType{ + newSchema: requireModuleSchema(t, schema.StateObjectType{ Name: "object1", KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}}, ValueFields: []schema.Field{{Name: "value1", Kind: schema.StringKind, Nullable: true}}, }), diff: ModuleSchemaDiff{ - ChangedObjectTypes: []ObjectTypeDiff{ + ChangedStateObjectTypes: []StateObjectTypeDiff{ { Name: "object1", ValueFieldsDiff: FieldsDiff{ @@ -113,17 +113,17 @@ func TestCompareModuleSchemas(t *testing.T) { }, { name: "object type changed, non-nullable value field added", - oldSchema: requireModuleSchema(t, schema.ObjectType{ + oldSchema: requireModuleSchema(t, schema.StateObjectType{ Name: "object1", KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}}, }), - newSchema: requireModuleSchema(t, schema.ObjectType{ + newSchema: requireModuleSchema(t, schema.StateObjectType{ Name: "object1", KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}}, ValueFields: []schema.Field{{Name: "value1", Kind: schema.StringKind}}, }), diff: ModuleSchemaDiff{ - ChangedObjectTypes: []ObjectTypeDiff{ + ChangedStateObjectTypes: []StateObjectTypeDiff{ { Name: "object1", ValueFieldsDiff: FieldsDiff{ @@ -136,16 +136,16 @@ func TestCompareModuleSchemas(t *testing.T) { }, { name: "object type changed, fields reordered", - oldSchema: requireModuleSchema(t, schema.ObjectType{ + oldSchema: requireModuleSchema(t, schema.StateObjectType{ Name: "object1", KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}, {Name: "key2", Kind: schema.StringKind}}, }), - newSchema: requireModuleSchema(t, schema.ObjectType{ + newSchema: requireModuleSchema(t, schema.StateObjectType{ Name: "object1", KeyFields: []schema.Field{{Name: "key2", Kind: schema.StringKind}, {Name: "key1", Kind: schema.StringKind}}, }), diff: ModuleSchemaDiff{ - ChangedObjectTypes: []ObjectTypeDiff{ + ChangedStateObjectTypes: []StateObjectTypeDiff{ { Name: "object1", KeyFieldsDiff: FieldsDiff{ @@ -159,11 +159,11 @@ func TestCompareModuleSchemas(t *testing.T) { }, { name: "enum type added, nullable value field added", - oldSchema: requireModuleSchema(t, schema.ObjectType{ + oldSchema: requireModuleSchema(t, schema.StateObjectType{ Name: "object1", KeyFields: []schema.Field{{Name: "key1", Kind: schema.Int32Kind}}, }), - newSchema: requireModuleSchema(t, schema.ObjectType{ + newSchema: requireModuleSchema(t, schema.StateObjectType{ Name: "object1", KeyFields: []schema.Field{{Name: "key1", Kind: schema.Int32Kind}}, ValueFields: []schema.Field{ @@ -177,7 +177,7 @@ func TestCompareModuleSchemas(t *testing.T) { }, schema.EnumType{Name: "enum1", Values: []schema.EnumValueDefinition{{Name: "a", Value: 1}, {Name: "b", Value: 2}}}), diff: ModuleSchemaDiff{ - ChangedObjectTypes: []ObjectTypeDiff{ + ChangedStateObjectTypes: []StateObjectTypeDiff{ { Name: "object1", ValueFieldsDiff: FieldsDiff{ @@ -201,7 +201,7 @@ func TestCompareModuleSchemas(t *testing.T) { { name: "enum type removed", oldSchema: requireModuleSchema(t, - schema.ObjectType{ + schema.StateObjectType{ Name: "object1", KeyFields: []schema.Field{{Name: "key1", Kind: schema.Int32Kind}}, ValueFields: []schema.Field{ @@ -213,12 +213,12 @@ func TestCompareModuleSchemas(t *testing.T) { }, }, schema.EnumType{Name: "enum1", Values: []schema.EnumValueDefinition{{Name: "a", Value: 1}, {Name: "b", Value: 2}}}), - newSchema: requireModuleSchema(t, schema.ObjectType{ + newSchema: requireModuleSchema(t, schema.StateObjectType{ Name: "object1", KeyFields: []schema.Field{{Name: "key1", Kind: schema.Int32Kind}}, }), diff: ModuleSchemaDiff{ - ChangedObjectTypes: []ObjectTypeDiff{ + ChangedStateObjectTypes: []StateObjectTypeDiff{ { Name: "object1", ValueFieldsDiff: FieldsDiff{ @@ -277,27 +277,27 @@ func TestCompareModuleSchemas(t *testing.T) { { name: "object type and enum type name switched", oldSchema: requireModuleSchema(t, - schema.ObjectType{ + schema.StateObjectType{ Name: "foo", KeyFields: []schema.Field{{Name: "key1", Kind: schema.EnumKind, ReferencedType: "bar"}}, }, schema.EnumType{Name: "bar", Values: []schema.EnumValueDefinition{{Name: "a", Value: 1}}}, ), newSchema: requireModuleSchema(t, - schema.ObjectType{ + schema.StateObjectType{ Name: "bar", KeyFields: []schema.Field{{Name: "key1", Kind: schema.EnumKind, ReferencedType: "foo"}}, }, schema.EnumType{Name: "foo", Values: []schema.EnumValueDefinition{{Name: "a", Value: 1}}}, ), diff: ModuleSchemaDiff{ - RemovedObjectTypes: []schema.ObjectType{ + RemovedStateObjectTypes: []schema.StateObjectType{ { Name: "foo", KeyFields: []schema.Field{{Name: "key1", Kind: schema.EnumKind, ReferencedType: "bar"}}, }, }, - AddedObjectTypes: []schema.ObjectType{ + AddedStateObjectTypes: []schema.StateObjectType{ { Name: "bar", KeyFields: []schema.Field{{Name: "key1", Kind: schema.EnumKind, ReferencedType: "foo"}}, @@ -332,6 +332,7 @@ func TestCompareModuleSchemas(t *testing.T) { } func requireModuleSchema(t *testing.T, types ...schema.Type) schema.ModuleSchema { + t.Helper() s, err := schema.CompileModuleSchema(types...) if err != nil { t.Fatal(err) diff --git a/schema/diff/object_type_diff.go b/schema/diff/state_object_diff.go similarity index 91% rename from schema/diff/object_type_diff.go rename to schema/diff/state_object_diff.go index 9f169a6df9ea..02c2d7bd46b4 100644 --- a/schema/diff/object_type_diff.go +++ b/schema/diff/state_object_diff.go @@ -2,10 +2,10 @@ package diff import "cosmossdk.io/schema" -// ObjectTypeDiff represents the difference between two object types. +// StateObjectTypeDiff represents the difference between two object types. // The Empty method of KeyFieldsDiff and ValueFieldsDiff can be used to determine // if there were any changes to the key fields or value fields. -type ObjectTypeDiff struct { +type StateObjectTypeDiff struct { // Name is the name of the object type. Name string @@ -39,8 +39,8 @@ type FieldsDiff struct { NewOrder []string } -func compareObjectType(oldObj, newObj schema.ObjectType) ObjectTypeDiff { - diff := ObjectTypeDiff{ +func compareObjectType(oldObj, newObj schema.StateObjectType) StateObjectTypeDiff { + diff := StateObjectTypeDiff{ Name: oldObj.TypeName(), } @@ -101,13 +101,13 @@ func compareFields(oldFields, newFields []schema.Field) FieldsDiff { } // Empty returns true if the object type diff has no changes. -func (o ObjectTypeDiff) Empty() bool { +func (o StateObjectTypeDiff) Empty() bool { return o.KeyFieldsDiff.Empty() && o.ValueFieldsDiff.Empty() } // HasCompatibleChanges returns true if the diff contains only compatible changes. // The only supported compatible change is adding nullable value fields. -func (o ObjectTypeDiff) HasCompatibleChanges() bool { +func (o StateObjectTypeDiff) HasCompatibleChanges() bool { if !o.KeyFieldsDiff.Empty() { return false } diff --git a/schema/diff/object_type_diff_test.go b/schema/diff/state_object_diff_test.go similarity index 84% rename from schema/diff/object_type_diff_test.go rename to schema/diff/state_object_diff_test.go index b29f8326c636..bf708d604ded 100644 --- a/schema/diff/object_type_diff_test.go +++ b/schema/diff/state_object_diff_test.go @@ -10,33 +10,33 @@ import ( func Test_objectTypeDiff(t *testing.T) { tt := []struct { name string - oldType schema.ObjectType - newType schema.ObjectType - diff ObjectTypeDiff - trueF func(ObjectTypeDiff) bool + oldType schema.StateObjectType + newType schema.StateObjectType + diff StateObjectTypeDiff + trueF func(StateObjectTypeDiff) bool hasCompatibleChanges bool }{ { name: "no change", - oldType: schema.ObjectType{ + oldType: schema.StateObjectType{ KeyFields: []schema.Field{{Name: "id", Kind: schema.Int32Kind}}, }, - newType: schema.ObjectType{ + newType: schema.StateObjectType{ KeyFields: []schema.Field{{Name: "id", Kind: schema.Int32Kind}}, }, - diff: ObjectTypeDiff{}, - trueF: ObjectTypeDiff.Empty, + diff: StateObjectTypeDiff{}, + trueF: StateObjectTypeDiff.Empty, hasCompatibleChanges: true, }, { name: "key fields changed", - oldType: schema.ObjectType{ + oldType: schema.StateObjectType{ KeyFields: []schema.Field{{Name: "id", Kind: schema.Int32Kind}}, }, - newType: schema.ObjectType{ + newType: schema.StateObjectType{ KeyFields: []schema.Field{{Name: "id", Kind: schema.StringKind}}, }, - diff: ObjectTypeDiff{ + diff: StateObjectTypeDiff{ KeyFieldsDiff: FieldsDiff{ Changed: []FieldDiff{ { @@ -47,18 +47,18 @@ func Test_objectTypeDiff(t *testing.T) { }, }, }, - trueF: func(d ObjectTypeDiff) bool { return !d.KeyFieldsDiff.Empty() }, + trueF: func(d StateObjectTypeDiff) bool { return !d.KeyFieldsDiff.Empty() }, hasCompatibleChanges: false, }, { name: "value fields changed", - oldType: schema.ObjectType{ + oldType: schema.StateObjectType{ ValueFields: []schema.Field{{Name: "name", Kind: schema.StringKind}}, }, - newType: schema.ObjectType{ + newType: schema.StateObjectType{ ValueFields: []schema.Field{{Name: "name", Kind: schema.Int32Kind}}, }, - diff: ObjectTypeDiff{ + diff: StateObjectTypeDiff{ ValueFieldsDiff: FieldsDiff{ Changed: []FieldDiff{ { @@ -69,52 +69,52 @@ func Test_objectTypeDiff(t *testing.T) { }, }, }, - trueF: func(d ObjectTypeDiff) bool { return !d.ValueFieldsDiff.Empty() }, + trueF: func(d StateObjectTypeDiff) bool { return !d.ValueFieldsDiff.Empty() }, hasCompatibleChanges: false, }, { name: "nullable value field added", - oldType: schema.ObjectType{ + oldType: schema.StateObjectType{ ValueFields: []schema.Field{{Name: "id", Kind: schema.Int32Kind}}, }, - newType: schema.ObjectType{ + newType: schema.StateObjectType{ ValueFields: []schema.Field{{Name: "id", Kind: schema.Int32Kind}, {Name: "name", Kind: schema.StringKind, Nullable: true}}, }, - diff: ObjectTypeDiff{ + diff: StateObjectTypeDiff{ ValueFieldsDiff: FieldsDiff{ Added: []schema.Field{{Name: "name", Kind: schema.StringKind, Nullable: true}}, }, }, - trueF: func(d ObjectTypeDiff) bool { return !d.ValueFieldsDiff.Empty() }, + trueF: func(d StateObjectTypeDiff) bool { return !d.ValueFieldsDiff.Empty() }, hasCompatibleChanges: true, }, { name: "non-nullable value field added", - oldType: schema.ObjectType{ + oldType: schema.StateObjectType{ ValueFields: []schema.Field{{Name: "id", Kind: schema.Int32Kind}}, }, - newType: schema.ObjectType{ + newType: schema.StateObjectType{ ValueFields: []schema.Field{{Name: "id", Kind: schema.Int32Kind}, {Name: "name", Kind: schema.StringKind}}, }, - diff: ObjectTypeDiff{ + diff: StateObjectTypeDiff{ ValueFieldsDiff: FieldsDiff{ Added: []schema.Field{{Name: "name", Kind: schema.StringKind}}, }, }, - trueF: func(d ObjectTypeDiff) bool { return !d.ValueFieldsDiff.Empty() }, + trueF: func(d StateObjectTypeDiff) bool { return !d.ValueFieldsDiff.Empty() }, hasCompatibleChanges: false, }, { name: "fields reordered", - oldType: schema.ObjectType{ + oldType: schema.StateObjectType{ KeyFields: []schema.Field{{Name: "id", Kind: schema.Int32Kind}, {Name: "name", Kind: schema.StringKind}}, ValueFields: []schema.Field{{Name: "x", Kind: schema.Int32Kind}, {Name: "y", Kind: schema.StringKind}}, }, - newType: schema.ObjectType{ + newType: schema.StateObjectType{ KeyFields: []schema.Field{{Name: "name", Kind: schema.StringKind}, {Name: "id", Kind: schema.Int32Kind}}, ValueFields: []schema.Field{{Name: "y", Kind: schema.StringKind}, {Name: "x", Kind: schema.Int32Kind}}, }, - diff: ObjectTypeDiff{ + diff: StateObjectTypeDiff{ KeyFieldsDiff: FieldsDiff{ OldOrder: []string{"id", "name"}, NewOrder: []string{"name", "id"}, @@ -124,7 +124,7 @@ func Test_objectTypeDiff(t *testing.T) { NewOrder: []string{"y", "x"}, }, }, - trueF: func(d ObjectTypeDiff) bool { return !d.KeyFieldsDiff.Empty() && !d.ValueFieldsDiff.Empty() }, + trueF: func(d StateObjectTypeDiff) bool { return !d.KeyFieldsDiff.Empty() && !d.ValueFieldsDiff.Empty() }, hasCompatibleChanges: false, }, } diff --git a/schema/enum.go b/schema/enum.go index 4783ccff6fc6..b52b01e1a522 100644 --- a/schema/enum.go +++ b/schema/enum.go @@ -41,7 +41,8 @@ func (e EnumType) TypeName() string { return e.Name } -func (EnumType) isType() {} +func (EnumType) isType() {} +func (EnumType) isReferenceType() {} // Validate validates the enum definition. func (e EnumType) Validate(TypeSet) error { diff --git a/schema/field.go b/schema/field.go index 0d762aa58dc6..dfbae6ed1b97 100644 --- a/schema/field.go +++ b/schema/field.go @@ -75,7 +75,7 @@ func (c Field) ValidateValue(value interface{}, typeSet TypeSet) error { } err := enumType.ValidateValue(value.(string)) if err != nil { - return fmt.Errorf("invalid value for enum field %q: %v", c.Name, err) + return fmt.Errorf("invalid value for enum field %q: %v", c.Name, err) //nolint:errorlint // false positive due to using go1.12 } default: } diff --git a/schema/fields.go b/schema/fields.go index d0bf1106dfec..90c66736d2e6 100644 --- a/schema/fields.go +++ b/schema/fields.go @@ -2,14 +2,14 @@ package schema import "fmt" -// ValidateObjectKey validates that the value conforms to the set of fields as a Key in an ObjectUpdate. -// See ObjectUpdate.Key for documentation on the requirements of such keys. +// ValidateObjectKey validates that the value conforms to the set of fields as a Key in an StateObjectUpdate. +// See StateObjectUpdate.Key for documentation on the requirements of such keys. func ValidateObjectKey(keyFields []Field, value interface{}, typeSet TypeSet) error { return validateFieldsValue(keyFields, value, typeSet) } -// ValidateObjectValue validates that the value conforms to the set of fields as a Value in an ObjectUpdate. -// See ObjectUpdate.Value for documentation on the requirements of such values. +// ValidateObjectValue validates that the value conforms to the set of fields as a Value in an StateObjectUpdate. +// See StateObjectUpdate.Value for documentation on the requirements of such values. func ValidateObjectValue(valueFields []Field, value interface{}, typeSet TypeSet) error { valueUpdates, ok := value.(ValueUpdates) if !ok { diff --git a/schema/module_schema.go b/schema/module_schema.go index a7e395e46e8d..2e93c692eb53 100644 --- a/schema/module_schema.go +++ b/schema/module_schema.go @@ -57,13 +57,13 @@ func (s ModuleSchema) Validate() error { } // ValidateObjectUpdate validates that the update conforms to the module schema. -func (s ModuleSchema) ValidateObjectUpdate(update ObjectUpdate) error { +func (s ModuleSchema) ValidateObjectUpdate(update StateObjectUpdate) error { typ, ok := s.types[update.TypeName] if !ok { return fmt.Errorf("object type %q not found in module schema", update.TypeName) } - objTyp, ok := typ.(ObjectType) + objTyp, ok := typ.(StateObjectType) if !ok { return fmt.Errorf("type %q is not an object type", update.TypeName) } @@ -91,14 +91,14 @@ func (s ModuleSchema) LookupEnumType(name string) (t EnumType, found bool) { } // LookupObjectType is a convenience method that looks up an ObjectType by name. -func (s ModuleSchema) LookupObjectType(name string) (t ObjectType, found bool) { +func (s ModuleSchema) LookupStateObjectType(name string) (t StateObjectType, found bool) { typ, found := s.LookupType(name) if !found { - return ObjectType{}, false + return StateObjectType{}, false } - t, ok := typ.(ObjectType) + t, ok := typ.(StateObjectType) if !ok { - return ObjectType{}, false + return StateObjectType{}, false } return t, true } @@ -119,9 +119,9 @@ func (s ModuleSchema) AllTypes(f func(Type) bool) { } // ObjectTypes iterators over all the object types in the schema in alphabetical order. -func (s ModuleSchema) ObjectTypes(f func(ObjectType) bool) { +func (s ModuleSchema) StateObjectTypes(f func(StateObjectType) bool) { s.AllTypes(func(t Type) bool { - objTyp, ok := t.(ObjectType) + objTyp, ok := t.(StateObjectType) if ok { return f(objTyp) } @@ -141,8 +141,8 @@ func (s ModuleSchema) EnumTypes(f func(EnumType) bool) { } type moduleSchemaJson struct { - ObjectTypes []ObjectType `json:"object_types"` - EnumTypes []EnumType `json:"enum_types"` + ObjectTypes []StateObjectType `json:"object_types"` + EnumTypes []EnumType `json:"enum_types"` } // MarshalJSON implements the json.Marshaler interface for ModuleSchema. @@ -151,7 +151,7 @@ type moduleSchemaJson struct { func (s ModuleSchema) MarshalJSON() ([]byte, error) { asJson := moduleSchemaJson{} - s.ObjectTypes(func(objType ObjectType) bool { + s.StateObjectTypes(func(objType StateObjectType) bool { asJson.ObjectTypes = append(asJson.ObjectTypes, objType) return true }) diff --git a/schema/module_schema_test.go b/schema/module_schema_test.go index e0d6a3f22ad7..109d226277ca 100644 --- a/schema/module_schema_test.go +++ b/schema/module_schema_test.go @@ -15,7 +15,7 @@ func TestModuleSchema_Validate(t *testing.T) { { name: "valid module schema", types: []Type{ - ObjectType{ + StateObjectType{ Name: "object1", KeyFields: []Field{ { @@ -30,7 +30,7 @@ func TestModuleSchema_Validate(t *testing.T) { { name: "invalid object type", types: []Type{ - ObjectType{ + StateObjectType{ Name: "", KeyFields: []Field{ { @@ -45,7 +45,7 @@ func TestModuleSchema_Validate(t *testing.T) { { name: "duplicate type name", types: []Type{ - ObjectType{ + StateObjectType{ Name: "type1", ValueFields: []Field{ { @@ -85,13 +85,13 @@ func TestModuleSchema_ValidateObjectUpdate(t *testing.T) { tests := []struct { name string moduleSchema ModuleSchema - objectUpdate ObjectUpdate + objectUpdate StateObjectUpdate errContains string }{ { name: "valid object update", moduleSchema: requireModuleSchema(t, - ObjectType{ + StateObjectType{ Name: "object1", KeyFields: []Field{ { @@ -101,7 +101,7 @@ func TestModuleSchema_ValidateObjectUpdate(t *testing.T) { }, }, ), - objectUpdate: ObjectUpdate{ + objectUpdate: StateObjectUpdate{ TypeName: "object1", Key: "abc", }, @@ -110,7 +110,7 @@ func TestModuleSchema_ValidateObjectUpdate(t *testing.T) { { name: "object type not found", moduleSchema: requireModuleSchema(t, - ObjectType{ + StateObjectType{ Name: "object1", KeyFields: []Field{ { @@ -120,7 +120,7 @@ func TestModuleSchema_ValidateObjectUpdate(t *testing.T) { }, }, ), - objectUpdate: ObjectUpdate{ + objectUpdate: StateObjectUpdate{ TypeName: "object2", Key: "abc", }, @@ -128,7 +128,7 @@ func TestModuleSchema_ValidateObjectUpdate(t *testing.T) { }, { name: "type name refers to an enum", - moduleSchema: requireModuleSchema(t, ObjectType{ + moduleSchema: requireModuleSchema(t, StateObjectType{ Name: "obj1", KeyFields: []Field{ { @@ -143,7 +143,7 @@ func TestModuleSchema_ValidateObjectUpdate(t *testing.T) { Values: []EnumValueDefinition{{Name: "a", Value: 1}, {Name: "b", Value: 2}}, }, ), - objectUpdate: ObjectUpdate{ + objectUpdate: StateObjectUpdate{ TypeName: "enum1", Key: "a", }, @@ -177,7 +177,7 @@ func requireModuleSchema(t *testing.T, types ...Type) ModuleSchema { } func TestModuleSchema_LookupType(t *testing.T) { - moduleSchema := requireModuleSchema(t, ObjectType{ + moduleSchema := requireModuleSchema(t, StateObjectType{ Name: "object1", KeyFields: []Field{ { @@ -187,7 +187,7 @@ func TestModuleSchema_LookupType(t *testing.T) { }, }) - objectType, ok := moduleSchema.LookupObjectType("object1") + objectType, ok := moduleSchema.LookupStateObjectType("object1") if !ok { t.Fatalf("expected to find object type \"object1\"") } @@ -200,7 +200,7 @@ func TestModuleSchema_LookupType(t *testing.T) { func exampleSchema(t *testing.T) ModuleSchema { t.Helper() return requireModuleSchema(t, - ObjectType{ + StateObjectType{ Name: "object1", KeyFields: []Field{ { @@ -210,7 +210,7 @@ func exampleSchema(t *testing.T) ModuleSchema { }, }, }, - ObjectType{ + StateObjectType{ Name: "object2", KeyFields: []Field{ { @@ -262,7 +262,7 @@ func TestModuleSchema_ObjectTypes(t *testing.T) { moduleSchema := exampleSchema(t) var typeNames []string - moduleSchema.ObjectTypes(func(typ ObjectType) bool { + moduleSchema.StateObjectTypes(func(typ StateObjectType) bool { typeNames = append(typeNames, typ.Name) return true }) @@ -274,7 +274,7 @@ func TestModuleSchema_ObjectTypes(t *testing.T) { typeNames = nil // scan just the first type and return false - moduleSchema.ObjectTypes(func(typ ObjectType) bool { + moduleSchema.StateObjectTypes(func(typ StateObjectType) bool { typeNames = append(typeNames, typ.Name) return false }) diff --git a/schema/object_type.go b/schema/state_object.go similarity index 90% rename from schema/object_type.go rename to schema/state_object.go index f961d06062e3..a4825726f685 100644 --- a/schema/object_type.go +++ b/schema/state_object.go @@ -2,8 +2,8 @@ package schema import "fmt" -// ObjectType describes an object type a module schema. -type ObjectType struct { +// StateObjectType describes an object type a module schema. +type StateObjectType struct { // Name is the name of the object type. It must be unique within the module schema amongst all object and enum // types and conform to the NameFormat regular expression. Name string `json:"name"` @@ -30,14 +30,14 @@ type ObjectType struct { } // TypeName implements the Type interface. -func (o ObjectType) TypeName() string { +func (o StateObjectType) TypeName() string { return o.Name } -func (ObjectType) isType() {} +func (StateObjectType) isType() {} // Validate validates the object type. -func (o ObjectType) Validate(typeSet TypeSet) error { +func (o StateObjectType) Validate(typeSet TypeSet) error { if !ValidateName(o.Name) { return fmt.Errorf("invalid object type name %q", o.Name) } @@ -82,7 +82,7 @@ func (o ObjectType) Validate(typeSet TypeSet) error { } // ValidateObjectUpdate validates that the update conforms to the object type. -func (o ObjectType) ValidateObjectUpdate(update ObjectUpdate, typeSet TypeSet) error { +func (o StateObjectType) ValidateObjectUpdate(update StateObjectUpdate, typeSet TypeSet) error { if o.Name != update.TypeName { return fmt.Errorf("object type name %q does not match update type name %q", o.Name, update.TypeName) } diff --git a/schema/object_type_test.go b/schema/state_object_test.go similarity index 86% rename from schema/object_type_test.go rename to schema/state_object_test.go index e2b68590241c..407586dd76e2 100644 --- a/schema/object_type_test.go +++ b/schema/state_object_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -var object1Type = ObjectType{ +var object1Type = StateObjectType{ Name: "object1", KeyFields: []Field{ { @@ -15,7 +15,7 @@ var object1Type = ObjectType{ }, } -var object2Type = ObjectType{ +var object2Type = StateObjectType{ KeyFields: []Field{ { Name: "field1", @@ -28,7 +28,7 @@ var object2Type = ObjectType{ }, } -var object3Type = ObjectType{ +var object3Type = StateObjectType{ Name: "object3", ValueFields: []Field{ { @@ -42,7 +42,7 @@ var object3Type = ObjectType{ }, } -var object4Type = ObjectType{ +var object4Type = StateObjectType{ Name: "object4", KeyFields: []Field{ { @@ -61,7 +61,7 @@ var object4Type = ObjectType{ func TestObjectType_Validate(t *testing.T) { tests := []struct { name string - objectType ObjectType + objectType StateObjectType errContains string }{ { @@ -71,7 +71,7 @@ func TestObjectType_Validate(t *testing.T) { }, { name: "empty object type name", - objectType: ObjectType{ + objectType: StateObjectType{ Name: "", KeyFields: []Field{ { @@ -84,7 +84,7 @@ func TestObjectType_Validate(t *testing.T) { }, { name: "invalid key field", - objectType: ObjectType{ + objectType: StateObjectType{ Name: "object1", KeyFields: []Field{ { @@ -97,7 +97,7 @@ func TestObjectType_Validate(t *testing.T) { }, { name: "invalid value field", - objectType: ObjectType{ + objectType: StateObjectType{ Name: "object1", ValueFields: []Field{ { @@ -109,12 +109,12 @@ func TestObjectType_Validate(t *testing.T) { }, { name: "no fields", - objectType: ObjectType{Name: "object0"}, + objectType: StateObjectType{Name: "object0"}, errContains: "has no key or value fields", }, { name: "duplicate field", - objectType: ObjectType{ + objectType: StateObjectType{ Name: "object1", KeyFields: []Field{ { @@ -133,7 +133,7 @@ func TestObjectType_Validate(t *testing.T) { }, { name: "duplicate field 22", - objectType: ObjectType{ + objectType: StateObjectType{ Name: "object1", KeyFields: []Field{ { @@ -150,7 +150,7 @@ func TestObjectType_Validate(t *testing.T) { }, { name: "nullable key field", - objectType: ObjectType{ + objectType: StateObjectType{ Name: "objectNullKey", KeyFields: []Field{ { @@ -164,7 +164,7 @@ func TestObjectType_Validate(t *testing.T) { }, { name: "float32 key field", - objectType: ObjectType{ + objectType: StateObjectType{ Name: "o1", KeyFields: []Field{ { @@ -177,7 +177,7 @@ func TestObjectType_Validate(t *testing.T) { }, { name: "float64 key field", - objectType: ObjectType{ + objectType: StateObjectType{ Name: "o1", KeyFields: []Field{ { @@ -190,7 +190,7 @@ func TestObjectType_Validate(t *testing.T) { }, { name: "json key field", - objectType: ObjectType{ + objectType: StateObjectType{ Name: "o1", KeyFields: []Field{ { @@ -222,14 +222,14 @@ func TestObjectType_Validate(t *testing.T) { func TestObjectType_ValidateObjectUpdate(t *testing.T) { tests := []struct { name string - objectType ObjectType - object ObjectUpdate + objectType StateObjectType + object StateObjectUpdate errContains string }{ { name: "wrong name", objectType: object1Type, - object: ObjectUpdate{ + object: StateObjectUpdate{ TypeName: "object2", Key: "hello", }, @@ -238,7 +238,7 @@ func TestObjectType_ValidateObjectUpdate(t *testing.T) { { name: "invalid value", objectType: object1Type, - object: ObjectUpdate{ + object: StateObjectUpdate{ TypeName: "object1", Key: 123, }, @@ -247,7 +247,7 @@ func TestObjectType_ValidateObjectUpdate(t *testing.T) { { name: "valid update", objectType: object4Type, - object: ObjectUpdate{ + object: StateObjectUpdate{ TypeName: "object4", Key: int32(123), Value: "hello", @@ -256,7 +256,7 @@ func TestObjectType_ValidateObjectUpdate(t *testing.T) { { name: "valid deletion", objectType: object4Type, - object: ObjectUpdate{ + object: StateObjectUpdate{ TypeName: "object4", Key: int32(123), Value: "ignored!", diff --git a/schema/object_update.go b/schema/state_object_update.go similarity index 91% rename from schema/object_update.go rename to schema/state_object_update.go index 455c4a850afb..84f221ffd1b7 100644 --- a/schema/object_update.go +++ b/schema/state_object_update.go @@ -2,8 +2,8 @@ package schema import "sort" -// ObjectUpdate represents an update operation on an object in a module's state. -type ObjectUpdate struct { +// StateObjectUpdate represents an update operation on an object in a module's state. +type StateObjectUpdate struct { // TypeName is the name of the object type in the module's schema. TypeName string @@ -19,7 +19,7 @@ type ObjectUpdate struct { Key interface{} // Value returns the non-primary key fields of the object and can either conform to the same constraints - // as ObjectUpdate.Key or it may be and instance of ValueUpdates. ValueUpdates can be used as a performance + // as StateObjectUpdate.Key or it may be and instance of ValueUpdates. ValueUpdates can be used as a performance // optimization to avoid copying the values of the object into the update and/or to omit unchanged fields. // If this is a delete operation, then this value is ignored and can be nil. Value interface{} diff --git a/schema/object_update_test.go b/schema/state_object_update_test.go similarity index 100% rename from schema/object_update_test.go rename to schema/state_object_update_test.go diff --git a/schema/testing/appdatasim/app_data.go b/schema/testing/appdatasim/app_data.go index 471cf5cb2b1f..c3e9e48ff04d 100644 --- a/schema/testing/appdatasim/app_data.go +++ b/schema/testing/appdatasim/app_data.go @@ -119,7 +119,7 @@ func (a *Simulator) BlockDataGenN(minUpdatesPerBlock, maxUpdatesPerBlock int) *r }) } -func (a *Simulator) formatUpdateKey(moduleName string, update schema.ObjectUpdate) string { +func (a *Simulator) formatUpdateKey(moduleName string, update schema.StateObjectUpdate) string { mod, err := a.state.GetModule(moduleName) if err != nil { panic(err) diff --git a/schema/testing/appdatasim/app_data_test.go b/schema/testing/appdatasim/app_data_test.go index eba8a8984ffb..146f9a398e98 100644 --- a/schema/testing/appdatasim/app_data_test.go +++ b/schema/testing/appdatasim/app_data_test.go @@ -24,7 +24,7 @@ func TestAppSimulator_mirror(t *testing.T) { }) } -func testAppSimulatorMirror(t *testing.T, retainDeletes bool) { // nolint: thelper // this isn't a test helper function +func testAppSimulatorMirror(t *testing.T, retainDeletes bool) { //nolint: thelper // this isn't a test helper function stateSimOpts := statesim.Options{CanRetainDeletions: retainDeletes} mirror, err := NewSimulator(Options{ StateSimOptions: stateSimOpts, diff --git a/schema/testing/example_schema.go b/schema/testing/example_schema.go index 81461b91b97f..c0937ac604d7 100644 --- a/schema/testing/example_schema.go +++ b/schema/testing/example_schema.go @@ -11,7 +11,7 @@ import ( var ExampleAppSchema = map[string]schema.ModuleSchema{ "all_kinds": mkAllKindsModule(), "test_cases": schema.MustCompileModuleSchema( - schema.ObjectType{ + schema.StateObjectType{ Name: "Singleton", KeyFields: []schema.Field{}, ValueFields: []schema.Field{ @@ -25,7 +25,7 @@ var ExampleAppSchema = map[string]schema.ModuleSchema{ }, }, }, - schema.ObjectType{ + schema.StateObjectType{ Name: "Simple", KeyFields: []schema.Field{ { @@ -44,7 +44,7 @@ var ExampleAppSchema = map[string]schema.ModuleSchema{ }, }, }, - schema.ObjectType{ + schema.StateObjectType{ Name: "TwoKeys", KeyFields: []schema.Field{ { @@ -57,7 +57,7 @@ var ExampleAppSchema = map[string]schema.ModuleSchema{ }, }, }, - schema.ObjectType{ + schema.StateObjectType{ Name: "ThreeKeys", KeyFields: []schema.Field{ { @@ -80,7 +80,7 @@ var ExampleAppSchema = map[string]schema.ModuleSchema{ }, }, }, - schema.ObjectType{ + schema.StateObjectType{ Name: "ManyValues", KeyFields: []schema.Field{ { @@ -107,7 +107,7 @@ var ExampleAppSchema = map[string]schema.ModuleSchema{ }, }, }, - schema.ObjectType{ + schema.StateObjectType{ Name: "RetainDeletions", KeyFields: []schema.Field{ { @@ -141,7 +141,7 @@ func mkAllKindsModule() schema.ModuleSchema { return schema.MustCompileModuleSchema(types...) } -func mkTestObjectType(kind schema.Kind) schema.ObjectType { +func mkTestObjectType(kind schema.Kind) schema.StateObjectType { field := schema.Field{ Kind: kind, } @@ -161,7 +161,7 @@ func mkTestObjectType(kind schema.Kind) schema.ObjectType { val2Field.Name = "valNullable" val2Field.Nullable = true - return schema.ObjectType{ + return schema.StateObjectType{ Name: fmt.Sprintf("test_%v", kind), KeyFields: []schema.Field{keyField}, ValueFields: []schema.Field{val1Field, val2Field}, diff --git a/schema/testing/fmt.go b/schema/testing/fmt.go index a7c2852b34ea..7e362cce63a5 100644 --- a/schema/testing/fmt.go +++ b/schema/testing/fmt.go @@ -11,7 +11,7 @@ import ( // ObjectKeyString formats the object key as a string deterministically for storage in a map. // The key must be valid for the object type and the object type must be valid. // No validation is performed here. -func ObjectKeyString(objectType schema.ObjectType, key any) string { +func ObjectKeyString(objectType schema.StateObjectType, key any) string { keyFields := objectType.KeyFields n := len(keyFields) switch n { diff --git a/schema/testing/fmt_test.go b/schema/testing/fmt_test.go index 49d539a9db6a..2ab312021fdf 100644 --- a/schema/testing/fmt_test.go +++ b/schema/testing/fmt_test.go @@ -8,12 +8,12 @@ import ( func TestObjectKeyString(t *testing.T) { tt := []struct { - objectType schema.ObjectType + objectType schema.StateObjectType key any expected string }{ { - objectType: schema.ObjectType{ + objectType: schema.StateObjectType{ Name: "Singleton", ValueFields: []schema.Field{ {Name: "Value", Kind: schema.StringKind}, @@ -23,7 +23,7 @@ func TestObjectKeyString(t *testing.T) { expected: "", }, { - objectType: schema.ObjectType{ + objectType: schema.StateObjectType{ Name: "Simple", KeyFields: []schema.Field{{Name: "Key", Kind: schema.StringKind}}, }, @@ -31,7 +31,7 @@ func TestObjectKeyString(t *testing.T) { expected: "Key=key", }, { - objectType: schema.ObjectType{ + objectType: schema.StateObjectType{ Name: "BytesAddressDecInt", KeyFields: []schema.Field{ {Name: "Bz", Kind: schema.BytesKind}, diff --git a/schema/testing/module_schema.go b/schema/testing/module_schema.go index c874ac73a9f1..6c480298ea43 100644 --- a/schema/testing/module_schema.go +++ b/schema/testing/module_schema.go @@ -16,7 +16,7 @@ func ModuleSchemaGen() *rapid.Generator[schema.ModuleSchema] { t.Fatal(err) } - objectTypes := distinctTypes(ObjectTypeGen(tempSchema)).Draw(t, "objectTypes") + objectTypes := distinctTypes(StateObjectTypeGen(tempSchema)).Draw(t, "objectTypes") allTypes := append(enumTypes, objectTypes...) modSchema, err := schema.CompileModuleSchema(allTypes...) diff --git a/schema/testing/object.go b/schema/testing/object.go index 3e7665aa4bc5..f6c6c81cba00 100644 --- a/schema/testing/object.go +++ b/schema/testing/object.go @@ -7,8 +7,8 @@ import ( "cosmossdk.io/schema" ) -// ObjectTypeGen generates random ObjectType's based on the validity criteria of object types. -func ObjectTypeGen(typeSet schema.TypeSet) *rapid.Generator[schema.ObjectType] { +// StateObjectTypeGen generates random StateObjectType's based on the validity criteria of object types. +func StateObjectTypeGen(typeSet schema.TypeSet) *rapid.Generator[schema.StateObjectType] { keyFieldsGen := rapid.SliceOfNDistinct(KeyFieldGen(typeSet), 1, 6, func(f schema.Field) string { return f.Name }) @@ -17,8 +17,8 @@ func ObjectTypeGen(typeSet schema.TypeSet) *rapid.Generator[schema.ObjectType] { return f.Name }) - return rapid.Custom(func(t *rapid.T) schema.ObjectType { - typ := schema.ObjectType{ + return rapid.Custom(func(t *rapid.T) schema.StateObjectType { + typ := schema.StateObjectType{ Name: NameGen.Filter(func(s string) bool { // filter out names that already exist in the schema _, found := typeSet.LookupType(s) @@ -31,7 +31,7 @@ func ObjectTypeGen(typeSet schema.TypeSet) *rapid.Generator[schema.ObjectType] { typ.RetainDeletions = boolGen.Draw(t, "retainDeletions") return typ - }).Filter(func(typ schema.ObjectType) bool { + }).Filter(func(typ schema.StateObjectType) bool { // filter out duplicate field names fieldNames := map[string]bool{} if hasDuplicateFieldNames(fieldNames, typ.KeyFields) { @@ -55,14 +55,14 @@ func hasDuplicateFieldNames(typeNames map[string]bool, fields []schema.Field) bo return false } -// ObjectInsertGen generates object updates that are valid for insertion. -func ObjectInsertGen(objectType schema.ObjectType, typeSet schema.TypeSet) *rapid.Generator[schema.ObjectUpdate] { - return ObjectUpdateGen(objectType, nil, typeSet) +// StateObjectInsertGen generates object updates that are valid for insertion. +func StateObjectInsertGen(objectType schema.StateObjectType, typeSet schema.TypeSet) *rapid.Generator[schema.StateObjectUpdate] { + return StateObjectUpdateGen(objectType, nil, typeSet) } -// ObjectUpdateGen generates object updates that are valid for updates using the provided state map as a source +// StateObjectUpdateGen generates object updates that are valid for updates using the provided state map as a source // of valid existing keys. -func ObjectUpdateGen(objectType schema.ObjectType, state *btree.Map[string, schema.ObjectUpdate], sch schema.TypeSet) *rapid.Generator[schema.ObjectUpdate] { +func StateObjectUpdateGen(objectType schema.StateObjectType, state *btree.Map[string, schema.StateObjectUpdate], sch schema.TypeSet) *rapid.Generator[schema.StateObjectUpdate] { keyGen := ObjectKeyGen(objectType.KeyFields, sch).Filter(func(key interface{}) bool { // filter out keys that exist in the state if state != nil { @@ -73,8 +73,8 @@ func ObjectUpdateGen(objectType schema.ObjectType, state *btree.Map[string, sche }) insertValueGen := ObjectValueGen(objectType.ValueFields, false, sch) updateValueGen := ObjectValueGen(objectType.ValueFields, true, sch) - return rapid.Custom(func(t *rapid.T) schema.ObjectUpdate { - update := schema.ObjectUpdate{ + return rapid.Custom(func(t *rapid.T) schema.StateObjectUpdate { + update := schema.StateObjectUpdate{ TypeName: objectType.Name, } diff --git a/schema/testing/object_test.go b/schema/testing/object_test.go index b28ca8b2d6cf..539cb87fe567 100644 --- a/schema/testing/object_test.go +++ b/schema/testing/object_test.go @@ -9,16 +9,16 @@ import ( func TestObject(t *testing.T) { rapid.Check(t, func(t *rapid.T) { - objectType := ObjectTypeGen(testEnumSchema).Draw(t, "object") + objectType := StateObjectTypeGen(testEnumSchema).Draw(t, "object") require.NoError(t, objectType.Validate(testEnumSchema)) }) } func TestObjectUpdate(t *testing.T) { rapid.Check(t, func(t *rapid.T) { - objectType := ObjectTypeGen(testEnumSchema).Draw(t, "object") + objectType := StateObjectTypeGen(testEnumSchema).Draw(t, "object") require.NoError(t, objectType.Validate(testEnumSchema)) - update := ObjectInsertGen(objectType, testEnumSchema).Draw(t, "update") + update := StateObjectInsertGen(objectType, testEnumSchema).Draw(t, "update") require.NoError(t, objectType.ValidateObjectUpdate(update, testEnumSchema)) }) } diff --git a/schema/testing/statesim/app.go b/schema/testing/statesim/app.go index c3c7399acc2b..cc31cab53649 100644 --- a/schema/testing/statesim/app.go +++ b/schema/testing/statesim/app.go @@ -42,7 +42,7 @@ func NewApp(appSchema map[string]schema.ModuleSchema, options Options) *App { moduleState, ok := app.moduleStates.Get(moduleName) require.True(t, ok) numUpdates := numUpdatesGen.Draw(t, "numUpdates") - updates := make([]schema.ObjectUpdate, numUpdates) + updates := make([]schema.StateObjectUpdate, numUpdates) for i := 0; i < numUpdates; i++ { update := moduleState.UpdateGen().Draw(t, fmt.Sprintf("update[%d]", i)) updates[i] = update diff --git a/schema/testing/statesim/module.go b/schema/testing/statesim/module.go index 4aa33a063506..3219db50177c 100644 --- a/schema/testing/statesim/module.go +++ b/schema/testing/statesim/module.go @@ -16,7 +16,7 @@ type Module struct { name string moduleSchema schema.ModuleSchema objectCollections *btree.Map[string, *ObjectCollection] - updateGen *rapid.Generator[schema.ObjectUpdate] + updateGen *rapid.Generator[schema.StateObjectUpdate] } // NewModule creates a new Module for the given module schema. @@ -24,7 +24,7 @@ func NewModule(name string, moduleSchema schema.ModuleSchema, options Options) * objectCollections := &btree.Map[string, *ObjectCollection]{} var objectTypeNames []string - moduleSchema.ObjectTypes(func(objectType schema.ObjectType) bool { + moduleSchema.StateObjectTypes(func(objectType schema.StateObjectType) bool { objectCollection := NewObjectCollection(objectType, options, moduleSchema) objectCollections.Set(objectType.Name, objectCollection) objectTypeNames = append(objectTypeNames, objectType.Name) @@ -33,7 +33,7 @@ func NewModule(name string, moduleSchema schema.ModuleSchema, options Options) * objectTypeSelector := rapid.SampledFrom(objectTypeNames) - updateGen := rapid.Custom(func(t *rapid.T) schema.ObjectUpdate { + updateGen := rapid.Custom(func(t *rapid.T) schema.StateObjectUpdate { objectType := objectTypeSelector.Draw(t, "objectType") objectColl, ok := objectCollections.Get(objectType) require.True(t, ok) @@ -49,7 +49,7 @@ func NewModule(name string, moduleSchema schema.ModuleSchema, options Options) * } // ApplyUpdate applies the given object update to the module. -func (o *Module) ApplyUpdate(update schema.ObjectUpdate) error { +func (o *Module) ApplyUpdate(update schema.StateObjectUpdate) error { objState, ok := o.objectCollections.Get(update.TypeName) if !ok { return fmt.Errorf("object type %s not found in module", update.TypeName) @@ -60,7 +60,7 @@ func (o *Module) ApplyUpdate(update schema.ObjectUpdate) error { // UpdateGen returns a generator for object updates. The generator is stateful and returns // a certain number of updates and deletes of existing objects in the module. -func (o *Module) UpdateGen() *rapid.Generator[schema.ObjectUpdate] { +func (o *Module) UpdateGen() *rapid.Generator[schema.StateObjectUpdate] { return o.updateGen } diff --git a/schema/testing/statesim/object_coll.go b/schema/testing/statesim/object_coll.go index e2c026a898a2..79434c7c2d8d 100644 --- a/schema/testing/statesim/object_coll.go +++ b/schema/testing/statesim/object_coll.go @@ -10,20 +10,20 @@ import ( schematesting "cosmossdk.io/schema/testing" ) -// ObjectCollection is a collection of objects of a specific type for testing purposes. +// ObjectCollection is a collection of state objects of a specific type for testing purposes. type ObjectCollection struct { options Options - objectType schema.ObjectType + objectType schema.StateObjectType typeSet schema.TypeSet - objects *btree.Map[string, schema.ObjectUpdate] - updateGen *rapid.Generator[schema.ObjectUpdate] + objects *btree.Map[string, schema.StateObjectUpdate] + updateGen *rapid.Generator[schema.StateObjectUpdate] valueFieldIndices map[string]int } // NewObjectCollection creates a new ObjectCollection for the given object type. -func NewObjectCollection(objectType schema.ObjectType, options Options, typeSet schema.TypeSet) *ObjectCollection { - objects := &btree.Map[string, schema.ObjectUpdate]{} - updateGen := schematesting.ObjectUpdateGen(objectType, objects, typeSet) +func NewObjectCollection(objectType schema.StateObjectType, options Options, typeSet schema.TypeSet) *ObjectCollection { + objects := &btree.Map[string, schema.StateObjectUpdate]{} + updateGen := schematesting.StateObjectUpdateGen(objectType, objects, typeSet) valueFieldIndices := make(map[string]int, len(objectType.ValueFields)) for i, field := range objectType.ValueFields { valueFieldIndices[field.Name] = i @@ -40,7 +40,7 @@ func NewObjectCollection(objectType schema.ObjectType, options Options, typeSet } // ApplyUpdate applies the given object update to the collection. -func (o *ObjectCollection) ApplyUpdate(update schema.ObjectUpdate) error { +func (o *ObjectCollection) ApplyUpdate(update schema.StateObjectUpdate) error { if update.TypeName != o.objectType.Name { return fmt.Errorf("update type name %q does not match object type name %q", update.TypeName, o.objectType.Name) } @@ -106,27 +106,27 @@ func (o *ObjectCollection) ApplyUpdate(update schema.ObjectUpdate) error { // UpdateGen returns a generator for random object updates against the collection. This generator // is stateful and returns a certain number of updates and deletes to existing objects. -func (o *ObjectCollection) UpdateGen() *rapid.Generator[schema.ObjectUpdate] { +func (o *ObjectCollection) UpdateGen() *rapid.Generator[schema.StateObjectUpdate] { return o.updateGen } // AllState iterates over the state of the collection by calling the given function with each item in // state represented as an object update. -func (o *ObjectCollection) AllState(f func(schema.ObjectUpdate, error) bool) { - o.objects.Scan(func(_ string, v schema.ObjectUpdate) bool { +func (o *ObjectCollection) AllState(f func(schema.StateObjectUpdate, error) bool) { + o.objects.Scan(func(_ string, v schema.StateObjectUpdate) bool { return f(v, nil) }) } -// GetObject returns the object with the given key from the collection represented as an ObjectUpdate -// itself. Deletions that are retained are returned as ObjectUpdate's with delete set to true. -func (o *ObjectCollection) GetObject(key interface{}) (update schema.ObjectUpdate, found bool, err error) { +// GetObject returns the object with the given key from the collection represented as an StateObjectUpdate +// itself. Deletions that are retained are returned as StateObjectUpdate's with delete set to true. +func (o *ObjectCollection) GetObject(key interface{}) (update schema.StateObjectUpdate, found bool, err error) { update, ok := o.objects.Get(schematesting.ObjectKeyString(o.objectType, key)) return update, ok, nil } // ObjectType returns the object type of the collection. -func (o *ObjectCollection) ObjectType() schema.ObjectType { +func (o *ObjectCollection) ObjectType() schema.StateObjectType { return o.objectType } diff --git a/schema/type.go b/schema/type.go index 9728675cd836..f441829bb132 100644 --- a/schema/type.go +++ b/schema/type.go @@ -1,7 +1,7 @@ package schema // Type is an interface that all types in the schema implement. -// Currently, these are ObjectType and EnumType. +// Currently, these are StateObjectType and EnumType. type Type interface { // TypeName returns the type's name. TypeName() string @@ -13,6 +13,15 @@ type Type interface { isType() } +// ReferenceType is a marker interface that all types that can be the target of Field.ReferencedType implement. +// Currently, this is only EnumType. +type ReferenceType interface { + Type + + // IsReferenceType is implemented if this is a reference type. + isReferenceType() +} + // TypeSet represents something that has types and allows them to be looked up by name. // Currently, the only implementation is ModuleSchema. type TypeSet interface { @@ -22,8 +31,8 @@ type TypeSet interface { // LookupEnumType is a convenience method that looks up an EnumType by name. LookupEnumType(name string) (t EnumType, found bool) - // LookupObjectType is a convenience method that looks up an ObjectType by name. - LookupObjectType(name string) (t ObjectType, found bool) + // LookupStateObjectType is a convenience method that looks up an StateObjectType by name. + LookupStateObjectType(name string) (t StateObjectType, found bool) // AllTypes calls the given function for each type in the type set. // This function is compatible with go 1.23 iterators and can be used like this: @@ -36,9 +45,9 @@ type TypeSet interface { // This function is compatible with go 1.23 iterators. EnumTypes(f func(EnumType) bool) - // ObjectTypes calls the given function for each ObjectType in the type set. + // StateObjectTypes calls the given function for each StateObjectType in the type set. // This function is compatible with go 1.23 iterators. - ObjectTypes(f func(ObjectType) bool) + StateObjectTypes(f func(objectType StateObjectType) bool) // isTypeSet is a private method that ensures that only types in this package can be marked as type sets. isTypeSet() @@ -62,14 +71,14 @@ func (s emptyTypeSet) LookupEnumType(string) (t EnumType, found bool) { return EnumType{}, false } -func (s emptyTypeSet) LookupObjectType(string) (t ObjectType, found bool) { - return ObjectType{}, false +func (s emptyTypeSet) LookupStateObjectType(string) (t StateObjectType, found bool) { + return StateObjectType{}, false } func (emptyTypeSet) AllTypes(func(Type) bool) {} func (s emptyTypeSet) EnumTypes(func(EnumType) bool) {} -func (s emptyTypeSet) ObjectTypes(func(ObjectType) bool) {} +func (s emptyTypeSet) StateObjectTypes(func(objectType StateObjectType) bool) {} func (emptyTypeSet) isTypeSet() {} diff --git a/schema/view/object.go b/schema/view/object.go index ac19edd6abb5..6813db5cb7b2 100644 --- a/schema/view/object.go +++ b/schema/view/object.go @@ -3,24 +3,24 @@ package view import "cosmossdk.io/schema" // ObjectCollection is the interface for viewing the state of a collection of objects in a module -// represented by ObjectUpdate's for an ObjectType. ObjectUpdates must not include +// represented by StateObjectUpdate's for an ObjectType. ObjectUpdates must not include // ValueUpdates in the Value field. When ValueUpdates are applied they must be // converted to individual value or array format depending on the number of fields in -// the value. For collections which retain deletions, ObjectUpdate's with the Delete +// the value. For collections which retain deletions, StateObjectUpdate's with the Delete // field set to true should be returned with the latest Value still intact. type ObjectCollection interface { // ObjectType returns the object type for the collection. - ObjectType() schema.ObjectType + ObjectType() schema.StateObjectType // GetObject returns the object update for the given key if it exists. And error should only be returned // if there was an error getting the object update. If the object does not exist but there was no error, // then found should be false and the error should be nil. - GetObject(key interface{}) (update schema.ObjectUpdate, found bool, err error) + GetObject(key interface{}) (update schema.StateObjectUpdate, found bool, err error) // AllState iterates over the state of the collection by calling the given function with each item in // state represented as an object update. If there is an error getting an object update, the error will be // non-nil and the object update should be empty. - AllState(f func(schema.ObjectUpdate, error) bool) + AllState(f func(schema.StateObjectUpdate, error) bool) // Len returns the number of objects in the collection. Len() (int, error) diff --git a/scripts/build/linting.mk b/scripts/build/linting.mk index 6e723c5f84f7..d174a06372f7 100644 --- a/scripts/build/linting.mk +++ b/scripts/build/linting.mk @@ -1,4 +1,4 @@ -golangci_version=v1.60.1 +golangci_version=v1.61.0 golangci_installed_version=$(shell golangci-lint version --format short 2>/dev/null) #? setup-pre-commit: Set pre-commit git hook diff --git a/scripts/build/simulations.mk b/scripts/build/simulations.mk index 4020d468a920..75182afc2cdd 100644 --- a/scripts/build/simulations.mk +++ b/scripts/build/simulations.mk @@ -2,7 +2,7 @@ #? test-sim-nondeterminism: Run non-determinism test for simapp test-sim-nondeterminism: @echo "Running non-determinism test..." - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout=30m -tags='sims' -run TestAppStateDeterminism \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=30m -tags='sims' -run TestAppStateDeterminism \ -NumBlocks=100 -BlockSize=200 -Period=0 # Requires an exported plugin. See store/streaming/README.md for documentation. @@ -16,45 +16,46 @@ test-sim-nondeterminism: # make test-sim-nondeterminism-streaming test-sim-nondeterminism-streaming: @echo "Running non-determinism-streaming test..." - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout=30m -tags='sims' -run TestAppStateDeterminism \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=30m -tags='sims' -run TestAppStateDeterminism \ -NumBlocks=100 -BlockSize=200 -Period=0 -EnableStreaming=true test-sim-custom-genesis-fast: @echo "Running custom genesis simulation..." @echo "By default, ${HOME}/.simapp/config/genesis.json will be used." - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout=30m -tags='sims' -run TestFullAppSimulation -Genesis=${HOME}/.simapp/config/genesis.json \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=30m -tags='sims' -run TestFullAppSimulation -Genesis=${HOME}/.simapp/config/genesis.json \ -NumBlocks=100 -BlockSize=200 -Seed=99 -Period=5 -SigverifyTx=false test-sim-import-export: @echo "Running application import/export simulation. This may take several minutes..." - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout 20m -tags='sims' -run TestAppImportExport \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 20m -tags='sims' -run TestAppImportExport \ -NumBlocks=50 -Period=5 test-sim-after-import: @echo "Running application simulation-after-import. This may take several minutes..." - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout 30m -tags='sims' -run TestAppSimulationAfterImport \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 30m -tags='sims' -run TestAppSimulationAfterImport \ -NumBlocks=50 -Period=5 test-sim-custom-genesis-multi-seed: @echo "Running multi-seed custom genesis simulation..." @echo "By default, ${HOME}/.simapp/config/genesis.json will be used." - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout 30m -tags='sims' -run TestFullAppSimulation -Genesis=${HOME}/.simapp/config/genesis.json \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 30m -tags='sims' -run TestFullAppSimulation -Genesis=${HOME}/.simapp/config/genesis.json \ -NumBlocks=400 -Period=5 test-sim-multi-seed-long: @echo "Running long multi-seed application simulation. This may take awhile!" - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout=2h -tags='sims' -run TestFullAppSimulation \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=2h -tags='sims' -run TestFullAppSimulation \ -NumBlocks=150 -Period=50 test-sim-multi-seed-short: @echo "Running short multi-seed application simulation. This may take awhile!" - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout 30m -tags='sims' -run TestFullAppSimulation \ - -NumBlocks=50 -Period=10 + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 30m -tags='sims' -run TestFullAppSimulation \ + -NumBlocks=50 -Period=10 -FauxMerkle=true + test-sim-benchmark-invariants: @echo "Running simulation invariant benchmarks..." - cd ${CURRENT_DIR}/simapp && go test -mod=readonly -benchmem -bench=BenchmarkInvariants -tags='sims' -run=^$ \ + cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -benchmem -bench=BenchmarkInvariants -tags='sims' -run=^$ \ -Enabled=true -NumBlocks=1000 -BlockSize=200 \ -Period=1 -Commit=true -Seed=57 -v -timeout 24h @@ -77,50 +78,23 @@ SIM_COMMIT ?= true test-sim-fuzz: @echo "Running application fuzz for numBlocks=2, blockSize=20. This may take awhile!" #ld flags are a quick fix to make it work on current osx - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -json -tags='sims' -ldflags="-extldflags=-Wl,-ld_classic" -timeout=60m -fuzztime=60m -run=^$$ -fuzz=FuzzFullAppSimulation -GenesisTime=1714720615 -NumBlocks=2 -BlockSize=20 + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -json -tags='sims' -ldflags="-extldflags=-Wl,-ld_classic" -timeout=60m -fuzztime=60m -run=^$$ -fuzz=FuzzFullAppSimulation -GenesisTime=1714720615 -NumBlocks=2 -BlockSize=20 #? test-sim-benchmark: Run benchmark test for simapp test-sim-benchmark: @echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!" - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -tags='sims' -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -tags='sims' -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \ -Enabled=true -NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h -# Requires an exported plugin. See store/streaming/README.md for documentation. -# -# example: -# export COSMOS_SDK_ABCI_V1= -# make test-sim-benchmark-streaming -# -# Using the built-in examples: -# export COSMOS_SDK_ABCI_V1=/store/streaming/abci/examples/file/file -# make test-sim-benchmark-streaming -test-sim-benchmark-streaming: - @echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!" - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -tags='sims' -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \ - -Enabled=true -NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h -EnableStreaming=true test-sim-profile: @echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!" - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -tags='sims' -benchmem -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -tags='sims' -benchmem -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \ -Enabled=true -NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h -cpuprofile cpu.out -memprofile mem.out -# Requires an exported plugin. See store/streaming/README.md for documentation. -# -# example: -# export COSMOS_SDK_ABCI_V1= -# make test-sim-profile-streaming -# -# Using the built-in examples: -# export COSMOS_SDK_ABCI_V1=/store/streaming/abci/examples/file/file -# make test-sim-profile-streaming -test-sim-profile-streaming: - @echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!" - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -tags='sims' -benchmem -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \ - -Enabled=true -NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h -cpuprofile cpu.out -memprofile mem.out -EnableStreaming=true - .PHONY: test-sim-profile test-sim-benchmark test-sim-fuzz #? benchmark: Run benchmark tests benchmark: - @go test -mod=readonly -bench=. $(PACKAGES_NOSIMULATION) + @go test -failfast -mod=readonly -bench=. $(PACKAGES_NOSIMULATION) .PHONY: benchmark diff --git a/scripts/mockgen.sh b/scripts/mockgen.sh index 57ef89cef1c5..1018534c81bc 100755 --- a/scripts/mockgen.sh +++ b/scripts/mockgen.sh @@ -13,7 +13,7 @@ $mockgen_cmd -source=x/nft/expected_keepers.go -package testutil -destination x/ $mockgen_cmd -source=x/feegrant/expected_keepers.go -package testutil -destination x/feegrant/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/mint/types/expected_keepers.go -package testutil -destination x/mint/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/auth/tx/config/expected_keepers.go -package testutil -destination x/auth/tx/testutil/expected_keepers_mocks.go -# $mockgen_cmd -source=x/auth/types/expected_keepers.go -package testutil -destination x/auth/testutil/expected_keepers_mocks.go +$mockgen_cmd -source=x/auth/types/expected_keepers.go -package testutil -destination x/auth/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/auth/ante/expected_keepers.go -package testutil -destination x/auth/ante/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/authz/expected_keepers.go -package testutil -destination x/authz/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/bank/types/expected_keepers.go -package testutil -destination x/bank/testutil/expected_keepers_mocks.go @@ -24,7 +24,7 @@ $mockgen_cmd -source=x/slashing/types/expected_keepers.go -package testutil -des $mockgen_cmd -source=x/genutil/types/expected_keepers.go -package testutil -destination x/genutil/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/gov/testutil/expected_keepers.go -package testutil -destination x/gov/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/staking/types/expected_keepers.go -package testutil -destination x/staking/testutil/expected_keepers_mocks.go -# $mockgen_cmd -source=x/auth/vesting/types/expected_keepers.go -package testutil -destination x/auth/vesting/testutil/expected_keepers_mocks.go +$mockgen_cmd -source=x/auth/vesting/types/expected_keepers.go -package testutil -destination x/auth/vesting/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/protocolpool/types/expected_keepers.go -package testutil -destination x/protocolpool/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/upgrade/types/expected_keepers.go -package testutil -destination x/upgrade/testutil/expected_keepers_mocks.go $mockgen_cmd -source=core/gas/service.go -package gas -destination core/testing/gas/service_mocks.go diff --git a/server/grpc/gogoreflection/fix_registration.go b/server/grpc/gogoreflection/fix_registration.go index ab1a18f592e9..5704f054ff61 100644 --- a/server/grpc/gogoreflection/fix_registration.go +++ b/server/grpc/gogoreflection/fix_registration.go @@ -3,10 +3,9 @@ package gogoreflection import ( "reflect" + _ "github.com/cosmos/cosmos-proto" // look above _ "github.com/cosmos/gogoproto/gogoproto" // required so it does register the gogoproto file descriptor gogoproto "github.com/cosmos/gogoproto/proto" - - _ "github.com/cosmos/cosmos-proto" // look above "github.com/golang/protobuf/proto" //nolint:staticcheck // migrate in a future pr ) @@ -42,12 +41,12 @@ func getExtension(extID int32, m proto.Message) *gogoproto.ExtensionDesc { for id, desc := range proto.RegisteredExtensions(m) { //nolint:staticcheck // keep for backward compatibility if id == extID { return &gogoproto.ExtensionDesc{ - ExtendedType: desc.ExtendedType, //nolint:staticcheck // keep for backward compatibility - ExtensionType: desc.ExtensionType, //nolint:staticcheck // keep for backward compatibility - Field: desc.Field, //nolint:staticcheck // keep for backward compatibility - Name: desc.Name, //nolint:staticcheck // keep for backward compatibility - Tag: desc.Tag, //nolint:staticcheck // keep for backward compatibility - Filename: desc.Filename, //nolint:staticcheck // keep for backward compatibility + ExtendedType: desc.ExtendedType, + ExtensionType: desc.ExtensionType, + Field: desc.Field, + Name: desc.Name, + Tag: desc.Tag, + Filename: desc.Filename, } } } diff --git a/server/grpc/gogoreflection/serverreflection.go b/server/grpc/gogoreflection/serverreflection.go index 559548cb31b3..11213a19d82f 100644 --- a/server/grpc/gogoreflection/serverreflection.go +++ b/server/grpc/gogoreflection/serverreflection.go @@ -184,7 +184,7 @@ func fqn(prefix, name string) string { // fileDescForType gets the file descriptor for the given type. // The given type should be a proto message. func (s *serverReflectionServer) fileDescForType(st reflect.Type) (*dpb.FileDescriptorProto, error) { - m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(protoMessage) + m, ok := reflect.Zero(reflect.PointerTo(st)).Interface().(protoMessage) if !ok { return nil, fmt.Errorf("failed to create message from type: %v", st) } @@ -232,7 +232,7 @@ func typeForName(name string) (reflect.Type, error) { } func fileDescContainingExtension(st reflect.Type, ext int32) (*dpb.FileDescriptorProto, error) { - m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(proto.Message) + m, ok := reflect.Zero(reflect.PointerTo(st)).Interface().(proto.Message) if !ok { return nil, fmt.Errorf("failed to create message from type: %v", st) } @@ -247,7 +247,7 @@ func fileDescContainingExtension(st reflect.Type, ext int32) (*dpb.FileDescripto } func (s *serverReflectionServer) allExtensionNumbersForType(st reflect.Type) ([]int32, error) { - m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(proto.Message) + m, ok := reflect.Zero(reflect.PointerTo(st)).Interface().(proto.Message) if !ok { return nil, fmt.Errorf("failed to create message from type: %v", st) } diff --git a/server/pruning_test.go b/server/pruning_test.go index 0c162fad61fe..08e1a6d0773c 100644 --- a/server/pruning_test.go +++ b/server/pruning_test.go @@ -49,8 +49,6 @@ func TestGetPruningOptionsFromFlags(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(j *testing.T) { viper.Reset() viper.SetDefault(FlagPruning, pruningtypes.PruningOptionDefault) diff --git a/server/start.go b/server/start.go index dce5ae198e6a..cff5807fbdb4 100644 --- a/server/start.go +++ b/server/start.go @@ -374,9 +374,7 @@ func startCmtNode( return nil, cleanupFn, err } - pv, err := pvm.LoadOrGenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile(), func() (cmtcrypto.PrivKey, error) { - return cmted25519.GenPrivKey(), nil - }) // TODO: make this modular + pv, err := pvm.LoadOrGenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile(), app.ValidatorKeyProvider()) if err != nil { return nil, cleanupFn, err } @@ -832,7 +830,7 @@ func testnetify[T types.Application](ctx *Context, testnetAppCreator types.AppCr _, context := getCtx(ctx, true) clientCreator := proxy.NewLocalClientCreator(cmtApp) metrics := node.DefaultMetricsProvider(cmtcfg.DefaultConfig().Instrumentation) - _, _, _, _, _, proxyMetrics, _, _ := metrics(genDoc.ChainID) // nolint: dogsled // function from comet + _, _, _, _, _, proxyMetrics, _, _ := metrics(genDoc.ChainID) //nolint: dogsled // function from comet proxyApp := proxy.NewAppConns(clientCreator, proxyMetrics) if err := proxyApp.Start(); err != nil { return nil, fmt.Errorf("error starting proxy app connections: %w", err) diff --git a/server/types/app.go b/server/types/app.go index d08cfff0ea9b..ca0a55ca1a0f 100644 --- a/server/types/app.go +++ b/server/types/app.go @@ -5,6 +5,7 @@ import ( "io" cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + cmtcrypto "github.com/cometbft/cometbft/crypto" cmttypes "github.com/cometbft/cometbft/types" "github.com/cosmos/gogoproto/grpc" @@ -57,6 +58,9 @@ type ( // SnapshotManager return the snapshot manager SnapshotManager() *snapshots.Manager + // ValidatorKeyProvider returns a function that generates a validator key + ValidatorKeyProvider() func() (cmtcrypto.PrivKey, error) + // Close is called in start cmd to gracefully cleanup resources. // Must be safe to be called multiple times. Close() error diff --git a/server/v2/api/grpc/gogoreflection/fix_registration.go b/server/v2/api/grpc/gogoreflection/fix_registration.go index ab1a18f592e9..d4edfc62b5e7 100644 --- a/server/v2/api/grpc/gogoreflection/fix_registration.go +++ b/server/v2/api/grpc/gogoreflection/fix_registration.go @@ -3,10 +3,9 @@ package gogoreflection import ( "reflect" + _ "github.com/cosmos/cosmos-proto" // look above _ "github.com/cosmos/gogoproto/gogoproto" // required so it does register the gogoproto file descriptor gogoproto "github.com/cosmos/gogoproto/proto" - - _ "github.com/cosmos/cosmos-proto" // look above "github.com/golang/protobuf/proto" //nolint:staticcheck // migrate in a future pr ) @@ -42,12 +41,12 @@ func getExtension(extID int32, m proto.Message) *gogoproto.ExtensionDesc { for id, desc := range proto.RegisteredExtensions(m) { //nolint:staticcheck // keep for backward compatibility if id == extID { return &gogoproto.ExtensionDesc{ - ExtendedType: desc.ExtendedType, //nolint:staticcheck // keep for backward compatibility - ExtensionType: desc.ExtensionType, //nolint:staticcheck // keep for backward compatibility - Field: desc.Field, //nolint:staticcheck // keep for backward compatibility - Name: desc.Name, //nolint:staticcheck // keep for backward compatibility - Tag: desc.Tag, //nolint:staticcheck // keep for backward compatibility - Filename: desc.Filename, //nolint:staticcheck // keep for backward compatibility + ExtendedType: desc.ExtendedType, + ExtensionType: desc.ExtensionType, + Field: desc.Field, + Name: desc.Name, + Tag: desc.Tag, + Filename: desc.Filename, } } } diff --git a/server/v2/api/grpc/gogoreflection/serverreflection.go b/server/v2/api/grpc/gogoreflection/serverreflection.go index 79f520545a87..5bd26b467e00 100644 --- a/server/v2/api/grpc/gogoreflection/serverreflection.go +++ b/server/v2/api/grpc/gogoreflection/serverreflection.go @@ -188,7 +188,7 @@ func fqn(prefix, name string) string { // fileDescForType gets the file descriptor for the given type. // The given type should be a proto message. func (s *serverReflectionServer) fileDescForType(st reflect.Type) (*dpb.FileDescriptorProto, error) { - m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(protoMessage) + m, ok := reflect.Zero(reflect.PointerTo(st)).Interface().(protoMessage) if !ok { return nil, fmt.Errorf("failed to create message from type: %v", st) } @@ -236,7 +236,7 @@ func typeForName(name string) (reflect.Type, error) { } func fileDescContainingExtension(st reflect.Type, ext int32) (*dpb.FileDescriptorProto, error) { - m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(gogoproto.Message) + m, ok := reflect.Zero(reflect.PointerTo(st)).Interface().(gogoproto.Message) if !ok { return nil, fmt.Errorf("failed to create message from type: %v", st) } @@ -251,7 +251,7 @@ func fileDescContainingExtension(st reflect.Type, ext int32) (*dpb.FileDescripto } func (s *serverReflectionServer) allExtensionNumbersForType(st reflect.Type) ([]int32, error) { - m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(gogoproto.Message) + m, ok := reflect.Zero(reflect.PointerTo(st)).Interface().(gogoproto.Message) if !ok { return nil, fmt.Errorf("failed to create message from type: %v", st) } diff --git a/server/v2/api/telemetry/metrics.go b/server/v2/api/telemetry/metrics.go index 39055af6739b..75e857bb8ec4 100644 --- a/server/v2/api/telemetry/metrics.go +++ b/server/v2/api/telemetry/metrics.go @@ -17,7 +17,7 @@ import ( // GlobalLabels defines the set of global labels that will be applied to all // metrics emitted using the telemetry package function wrappers. -var GlobalLabels = []metrics.Label{} // nolint: ignore // false positive +var GlobalLabels = []metrics.Label{} //nolint: ignore // false positive // NewLabel creates a new instance of Label with name and value func NewLabel(name, value string) metrics.Label { diff --git a/server/v2/cometbft/abci.go b/server/v2/cometbft/abci.go index 06c1e43e5ecb..537b3e2dc5f5 100644 --- a/server/v2/cometbft/abci.go +++ b/server/v2/cometbft/abci.go @@ -33,15 +33,14 @@ import ( var _ abci.Application = (*Consensus[transaction.Tx])(nil) type Consensus[T transaction.Tx] struct { - logger log.Logger - appName, version string - consensusAuthority string // Set by the application to grant authority to the consensus engine to send messages to the consensus module - app *appmanager.AppManager[T] - txCodec transaction.Codec[T] - store types.Store - streaming streaming.Manager - snapshotManager *snapshots.Manager - mempool mempool.Mempool[T] + logger log.Logger + appName, version string + app *appmanager.AppManager[T] + txCodec transaction.Codec[T] + store types.Store + streaming streaming.Manager + snapshotManager *snapshots.Manager + mempool mempool.Mempool[T] cfg Config indexedEvents map[string]struct{} @@ -67,7 +66,6 @@ type Consensus[T transaction.Tx] struct { func NewConsensus[T transaction.Tx]( logger log.Logger, appName string, - consensusAuthority string, // TODO remove app *appmanager.AppManager[T], mp mempool.Mempool[T], indexedEvents map[string]struct{}, @@ -80,7 +78,6 @@ func NewConsensus[T transaction.Tx]( return &Consensus[T]{ appName: appName, version: getCometBFTServerVersion(), - consensusAuthority: consensusAuthority, grpcMethodsMap: gRPCMethodsMap, app: app, cfg: cfg, @@ -129,11 +126,16 @@ func (c *Consensus[T]) CheckTx(ctx context.Context, req *abciproto.CheckTxReques return nil, err } + events, err := intoABCIEvents(resp.Events, c.indexedEvents) + if err != nil { + return nil, err + } + cometResp := &abciproto.CheckTxResponse{ Code: resp.Code, GasWanted: uint64ToInt64(resp.GasWanted), GasUsed: uint64ToInt64(resp.GasUsed), - Events: intoABCIEvents(resp.Events, c.indexedEvents), + Events: events, } if resp.Error != nil { cometResp.Code = 1 @@ -246,7 +248,6 @@ func (c *Consensus[T]) InitChain(ctx context.Context, req *abciproto.InitChainRe if req.ConsensusParams != nil { ctx = context.WithValue(ctx, corecontext.CometParamsInitInfoKey, &consensustypes.MsgUpdateParams{ - Authority: c.consensusAuthority, Block: req.ConsensusParams.Block, Evidence: req.ConsensusParams.Evidence, Validator: req.ConsensusParams.Validator, @@ -471,9 +472,10 @@ func (c *Consensus[T]) FinalizeBlock( } // remove txs from the mempool - err = c.mempool.Remove(decodedTxs) - if err != nil { - return nil, fmt.Errorf("unable to remove txs: %w", err) + for _, tx := range decodedTxs { + if err = c.mempool.Remove(tx); err != nil { + return nil, fmt.Errorf("unable to remove tx: %w", err) + } } c.lastCommittedHeight.Store(req.Height) diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index 0a4f1b16f975..72801a611971 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -334,9 +334,6 @@ func TestConsensus_ExtendVote(t *testing.T) { Block: &v1.BlockParams{ MaxGas: 5000000, }, - Abci: &v1.ABCIParams{ - VoteExtensionsEnableHeight: 2, - }, Feature: &v1.FeatureParams{ VoteExtensionsEnableHeight: &gogotypes.Int64Value{Value: 2}, }, @@ -376,9 +373,6 @@ func TestConsensus_VerifyVoteExtension(t *testing.T) { Block: &v1.BlockParams{ MaxGas: 5000000, }, - Abci: &v1.ABCIParams{ - VoteExtensionsEnableHeight: 2, - }, Feature: &v1.FeatureParams{ VoteExtensionsEnableHeight: &gogotypes.Int64Value{Value: 2}, }, @@ -537,6 +531,7 @@ func TestConsensus_ProcessProposal_With_Handler(t *testing.T) { Height: 1, Txs: [][]byte{mockTx.Bytes(), append(mockTx.Bytes(), []byte("bad")...), mockTx.Bytes(), mockTx.Bytes()}, }) + require.NoError(t, err) require.Equal(t, res.Status, abciproto.PROCESS_PROPOSAL_STATUS_REJECT) } @@ -642,9 +637,6 @@ func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock. Block: &v1.BlockParams{ MaxGas: 300000, }, - Abci: &v1.ABCIParams{ - VoteExtensionsEnableHeight: 2, - }, Feature: &v1.FeatureParams{ VoteExtensionsEnableHeight: &gogotypes.Int64Value{Value: 2}, }, @@ -694,7 +686,7 @@ func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock. am, err := b.Build() require.NoError(t, err) - return NewConsensus[mock.Tx](log.NewNopLogger(), "testing-app", "authority", am, mempool, map[string]struct{}{}, nil, mockStore, Config{AppTomlConfig: DefaultAppTomlConfig()}, mock.TxCodec{}, "test") + return NewConsensus[mock.Tx](log.NewNopLogger(), "testing-app", am, mempool, map[string]struct{}{}, nil, mockStore, Config{AppTomlConfig: DefaultAppTomlConfig()}, mock.TxCodec{}, "test") } // Check target version same with store's latest version diff --git a/server/v2/cometbft/config.go b/server/v2/cometbft/config.go index 81f3aeb33354..4525e7563c27 100644 --- a/server/v2/cometbft/config.go +++ b/server/v2/cometbft/config.go @@ -2,6 +2,8 @@ package cometbft import ( cmtcfg "github.com/cometbft/cometbft/config" + + "cosmossdk.io/server/v2/cometbft/mempool" ) // Config is the configuration for the CometBFT application @@ -20,6 +22,7 @@ func DefaultAppTomlConfig() *AppTomlConfig { Transport: "socket", Trace: false, Standalone: false, + Mempool: mempool.DefaultConfig(), } } @@ -32,6 +35,9 @@ type AppTomlConfig struct { Transport string `mapstructure:"transport" toml:"transport" comment:"transport defines the CometBFT RPC server transport protocol: socket, grpc"` Trace bool `mapstructure:"trace" toml:"trace" comment:"trace enables the CometBFT RPC server to output trace information about its internal operations."` Standalone bool `mapstructure:"standalone" toml:"standalone" comment:"standalone starts the application without the CometBFT node. The node should be started separately."` + + // Sub configs + Mempool mempool.Config `mapstructure:"mempool" toml:"mempool" comment:"mempool defines the configuration for the SDK built-in app-side mempool implementations."` } // CfgOption is a function that allows to overwrite the default server configuration. diff --git a/server/v2/cometbft/flags.go b/server/v2/cometbft/flags.go index 55fa0a14e771..216755f9885b 100644 --- a/server/v2/cometbft/flags.go +++ b/server/v2/cometbft/flags.go @@ -51,10 +51,11 @@ func prefix(f string) string { // Server flags var ( - Standalone = prefix("standalone") - FlagAddress = prefix("address") - FlagTransport = prefix("transport") - FlagHaltHeight = prefix("halt-height") - FlagHaltTime = prefix("halt-time") - FlagTrace = prefix("trace") + Standalone = prefix("standalone") + FlagAddress = prefix("address") + FlagTransport = prefix("transport") + FlagHaltHeight = prefix("halt-height") + FlagHaltTime = prefix("halt-time") + FlagTrace = prefix("trace") + FlagMempoolMaxTxs = prefix("mempool.max-txs") ) diff --git a/server/v2/cometbft/go.mod b/server/v2/cometbft/go.mod index 334ec6e05049..510a301451a6 100644 --- a/server/v2/cometbft/go.mod +++ b/server/v2/cometbft/go.mod @@ -19,7 +19,7 @@ replace ( require ( cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 cosmossdk.io/server/v2 v2.0.0-00010101000000-000000000000 @@ -46,7 +46,7 @@ require ( cosmossdk.io/depinject v1.0.0 // indirect cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 // indirect cosmossdk.io/math v1.3.0 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect @@ -140,7 +140,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/server/v2/cometbft/go.sum b/server/v2/cometbft/go.sum index 9d4fcef2a2e2..5b31f66326a9 100644 --- a/server/v2/cometbft/go.sum +++ b/server/v2/cometbft/go.sum @@ -6,8 +6,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -18,8 +18,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -406,8 +406,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/server/v2/cometbft/handlers/defaults.go b/server/v2/cometbft/handlers/defaults.go index 18ad38669c9c..d8f43bb2fd25 100644 --- a/server/v2/cometbft/handlers/defaults.go +++ b/server/v2/cometbft/handlers/defaults.go @@ -79,7 +79,7 @@ func (h *DefaultProposalHandler[T]) PrepareHandler() PrepareHandler[T] { // check again. _, err := app.ValidateTx(ctx, memTx) if err != nil { - err := h.mempool.Remove([]T{memTx}) + err := h.mempool.Remove(memTx) if err != nil && !errors.Is(err, mempool.ErrTxNotFound) { return nil, err } diff --git a/server/v2/cometbft/internal/mock/mock_mempool.go b/server/v2/cometbft/internal/mock/mock_mempool.go index 89d51e955fae..401b12d60139 100644 --- a/server/v2/cometbft/internal/mock/mock_mempool.go +++ b/server/v2/cometbft/internal/mock/mock_mempool.go @@ -15,5 +15,6 @@ type MockMempool[T transaction.Tx] struct{} func (MockMempool[T]) Insert(context.Context, T) error { return nil } func (MockMempool[T]) Select(context.Context, []T) mempool.Iterator[T] { return nil } +func (MockMempool[T]) SelectBy(context.Context, []T, func(T) bool) {} func (MockMempool[T]) CountTx() int { return 0 } -func (MockMempool[T]) Remove([]T) error { return nil } +func (MockMempool[T]) Remove(T) error { return nil } diff --git a/server/v2/cometbft/mempool/config.go b/server/v2/cometbft/mempool/config.go index 38de18844107..e07d6a6e7167 100644 --- a/server/v2/cometbft/mempool/config.go +++ b/server/v2/cometbft/mempool/config.go @@ -1,11 +1,16 @@ package mempool -// Config defines the configurations for the SDK built-in app-side mempool -// implementations. +var DefaultMaxTx = -1 + +// Config defines the configurations for the SDK built-in app-side mempool implementations. type Config struct { - // MaxTxs defines the behavior of the mempool. A negative value indicates - // the mempool is disabled entirely, zero indicates that the mempool is - // unbounded in how many txs it may contain, and a positive value indicates - // the maximum amount of txs it may contain. - MaxTxs int `mapstructure:"max-txs"` + // MaxTxs defines the maximum number of transactions that can be in the mempool. + MaxTxs int `mapstructure:"max-txs" toml:"max-txs" comment:"max-txs defines the maximum number of transactions that can be in the mempool. A value of 0 indicates an unbounded mempool, a negative value disables the app-side mempool."` +} + +// DefaultConfig returns a default configuration for the SDK built-in app-side mempool implementations. +func DefaultConfig() Config { + return Config{ + MaxTxs: DefaultMaxTx, + } } diff --git a/server/v2/cometbft/mempool/doc.go b/server/v2/cometbft/mempool/doc.go index f9857f3a9fae..eb6c72aced18 100644 --- a/server/v2/cometbft/mempool/doc.go +++ b/server/v2/cometbft/mempool/doc.go @@ -1,6 +1,2 @@ -/* -The mempool package defines a few mempool services which can be used in conjunction with your consensus implementation - -*/ - +// Package mempool defines a few mempool services which can be used in conjunction with your consensus implementation. package mempool diff --git a/server/v2/cometbft/mempool/mempool.go b/server/v2/cometbft/mempool/mempool.go index 3cb81c871508..0b28c5a2b922 100644 --- a/server/v2/cometbft/mempool/mempool.go +++ b/server/v2/cometbft/mempool/mempool.go @@ -19,13 +19,18 @@ type Mempool[T transaction.Tx] interface { Insert(context.Context, T) error // Select returns an Iterator over the app-side mempool. If txs are specified, - // then they shall be incorporated into the Iterator. The Iterator must be - // closed by the caller. + // then they shall be incorporated into the Iterator. The Iterator is not thread-safe to use. Select(context.Context, []T) Iterator[T] + // SelectBy use callback to iterate over the mempool, it's thread-safe to use. + SelectBy(context.Context, []T, func(T) bool) + + // CountTx returns the number of transactions currently in the mempool. + CountTx() int + // Remove attempts to remove a transaction from the mempool, returning an error // upon failure. - Remove([]T) error + Remove(T) error } // Iterator defines an app-side mempool iterator interface that is as minimal as diff --git a/server/v2/cometbft/mempool/noop.go b/server/v2/cometbft/mempool/noop.go index 86cea55e2c53..25cffcf69979 100644 --- a/server/v2/cometbft/mempool/noop.go +++ b/server/v2/cometbft/mempool/noop.go @@ -4,8 +4,11 @@ import ( "context" "cosmossdk.io/core/transaction" + + sdk "github.com/cosmos/cosmos-sdk/types" ) +var _ Mempool[sdk.Tx] = (*NoOpMempool[sdk.Tx])(nil) // verify interface at compile time var _ Mempool[transaction.Tx] = (*NoOpMempool[transaction.Tx])(nil) // NoOpMempool defines a no-op mempool. Transactions are completely discarded and @@ -16,7 +19,8 @@ var _ Mempool[transaction.Tx] = (*NoOpMempool[transaction.Tx])(nil) // is FIFO-ordered by default. type NoOpMempool[T transaction.Tx] struct{} -func (NoOpMempool[T]) Insert(context.Context, T) error { return nil } -func (NoOpMempool[T]) Select(context.Context, []T) Iterator[T] { return nil } -func (NoOpMempool[T]) CountTx() int { return 0 } -func (NoOpMempool[T]) Remove([]T) error { return nil } +func (NoOpMempool[T]) Insert(context.Context, T) error { return nil } +func (NoOpMempool[T]) Select(context.Context, []T) Iterator[T] { return nil } +func (NoOpMempool[T]) SelectBy(context.Context, []T, func(T) bool) {} +func (NoOpMempool[T]) CountTx() int { return 0 } +func (NoOpMempool[T]) Remove(T) error { return nil } diff --git a/server/v2/cometbft/options.go b/server/v2/cometbft/options.go index 1e0a389882e0..0f5091da70a0 100644 --- a/server/v2/cometbft/options.go +++ b/server/v2/cometbft/options.go @@ -1,6 +1,9 @@ package cometbft import ( + cmtcrypto "github.com/cometbft/cometbft/crypto" + cmted22519 "github.com/cometbft/cometbft/crypto/ed25519" + "cosmossdk.io/core/transaction" "cosmossdk.io/server/v2/cometbft/handlers" "cosmossdk.io/server/v2/cometbft/mempool" @@ -8,15 +11,19 @@ import ( "cosmossdk.io/store/v2/snapshots" ) +type keyGenF = func() (cmtcrypto.PrivKey, error) + // ServerOptions defines the options for the CometBFT server. +// When an option takes a map[string]any, it can access the app.tom's cometbft section and the config.toml config. type ServerOptions[T transaction.Tx] struct { - Mempool mempool.Mempool[T] PrepareProposalHandler handlers.PrepareHandler[T] ProcessProposalHandler handlers.ProcessHandler[T] VerifyVoteExtensionHandler handlers.VerifyVoteExtensionhandler ExtendVoteHandler handlers.ExtendVoteHandler + KeygenF keyGenF - SnapshotOptions snapshots.SnapshotOptions + Mempool func(cfg map[string]any) mempool.Mempool[T] + SnapshotOptions func(cfg map[string]any) snapshots.SnapshotOptions AddrPeerFilter types.PeerFilter // filter peers by address and port IdPeerFilter types.PeerFilter // filter peers by node ID @@ -26,13 +33,14 @@ type ServerOptions[T transaction.Tx] struct { // It defaults to a NoOpMempool and NoOp handlers. func DefaultServerOptions[T transaction.Tx]() ServerOptions[T] { return ServerOptions[T]{ - Mempool: mempool.NoOpMempool[T]{}, PrepareProposalHandler: handlers.NoOpPrepareProposal[T](), ProcessProposalHandler: handlers.NoOpProcessProposal[T](), VerifyVoteExtensionHandler: handlers.NoOpVerifyVoteExtensionHandler(), ExtendVoteHandler: handlers.NoOpExtendVote(), - SnapshotOptions: snapshots.NewSnapshotOptions(0, 0), + Mempool: func(cfg map[string]any) mempool.Mempool[T] { return mempool.NoOpMempool[T]{} }, + SnapshotOptions: func(cfg map[string]any) snapshots.SnapshotOptions { return snapshots.NewSnapshotOptions(0, 0) }, AddrPeerFilter: nil, IdPeerFilter: nil, + KeygenF: func() (cmtcrypto.PrivKey, error) { return cmted22519.GenPrivKey(), nil }, } } diff --git a/server/v2/cometbft/server.go b/server/v2/cometbft/server.go index 26cd99ff97cd..2f402522c099 100644 --- a/server/v2/cometbft/server.go +++ b/server/v2/cometbft/server.go @@ -11,8 +11,6 @@ import ( abciserver "github.com/cometbft/cometbft/abci/server" cmtcmd "github.com/cometbft/cometbft/cmd/cometbft/commands" cmtcfg "github.com/cometbft/cometbft/config" - cmtcrypto "github.com/cometbft/cometbft/crypto" - cmted25519 "github.com/cometbft/cometbft/crypto/ed25519" "github.com/cometbft/cometbft/node" "github.com/cometbft/cometbft/p2p" pvm "github.com/cometbft/cometbft/privval" @@ -24,6 +22,7 @@ import ( "cosmossdk.io/log" serverv2 "cosmossdk.io/server/v2" cometlog "cosmossdk.io/server/v2/cometbft/log" + "cosmossdk.io/server/v2/cometbft/mempool" "cosmossdk.io/server/v2/cometbft/types" "cosmossdk.io/store/v2/snapshots" @@ -103,9 +102,8 @@ func (s *CometBFTServer[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logg consensus := NewConsensus( s.logger, appI.Name(), - appI.GetConsensusAuthority(), appI.GetAppManager(), - s.serverOptions.Mempool, + s.serverOptions.Mempool(cfg), indexEvents, appI.GetGPRCMethodsToMessageMap(), store, @@ -127,7 +125,7 @@ func (s *CometBFTServer[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logg if err != nil { return err } - consensus.snapshotManager = snapshots.NewManager(snapshotStore, s.serverOptions.SnapshotOptions, sc, ss, nil, s.logger) + consensus.snapshotManager = snapshots.NewManager(snapshotStore, s.serverOptions.SnapshotOptions(cfg), sc, ss, nil, s.logger) s.Consensus = consensus @@ -159,9 +157,7 @@ func (s *CometBFTServer[T]) Start(ctx context.Context) error { pv, err := pvm.LoadOrGenFilePV( s.config.ConfigTomlConfig.PrivValidatorKeyFile(), s.config.ConfigTomlConfig.PrivValidatorStateFile(), - func() (cmtcrypto.PrivKey, error) { - return cmted25519.GenPrivKey(), nil - }, + s.serverOptions.KeygenF, ) if err != nil { return err @@ -240,6 +236,7 @@ func (s *CometBFTServer[T]) StartCmdFlags() *pflag.FlagSet { flags.Uint64(FlagHaltTime, 0, "Minimum block time (in Unix seconds) at which to gracefully halt the chain and shutdown the node") flags.Bool(FlagTrace, false, "Provide full stack traces for errors in ABCI Log") flags.Bool(Standalone, false, "Run app without CometBFT") + flags.Int(FlagMempoolMaxTxs, mempool.DefaultMaxTx, "Sets MaxTx value for the app-side mempool") // add comet flags, we use an empty command to avoid duplicating CometBFT's AddNodeFlags. // we can then merge the flag sets. diff --git a/server/v2/cometbft/streaming.go b/server/v2/cometbft/streaming.go index 0c8af07aa547..54abe20aaa96 100644 --- a/server/v2/cometbft/streaming.go +++ b/server/v2/cometbft/streaming.go @@ -21,20 +21,28 @@ func (c *Consensus[T]) streamDeliverBlockChanges( // convert txresults to streaming txresults streamingTxResults := make([]*streaming.ExecTxResult, len(txResults)) for i, txResult := range txResults { + events, err := streaming.IntoStreamingEvents(txResult.Events) + if err != nil { + return err + } streamingTxResults[i] = &streaming.ExecTxResult{ Code: txResult.Code, GasWanted: uint64ToInt64(txResult.GasWanted), GasUsed: uint64ToInt64(txResult.GasUsed), - Events: streaming.IntoStreamingEvents(txResult.Events), + Events: events, } } for _, streamingListener := range c.streaming.Listeners { + events, err := streaming.IntoStreamingEvents(events) + if err != nil { + return err + } if err := streamingListener.ListenDeliverBlock(ctx, streaming.ListenDeliverBlockRequest{ BlockHeight: height, Txs: txs, TxResults: streamingTxResults, - Events: streaming.IntoStreamingEvents(events), + Events: events, }); err != nil { c.logger.Error("ListenDeliverBlock listening hook failed", "height", height, "err", err) } diff --git a/server/v2/cometbft/utils.go b/server/v2/cometbft/utils.go index 6aaf1b5401d6..d48147e0a243 100644 --- a/server/v2/cometbft/utils.go +++ b/server/v2/cometbft/utils.go @@ -73,9 +73,19 @@ func finalizeBlockResponse( ) (*abci.FinalizeBlockResponse, error) { allEvents := append(in.BeginBlockEvents, in.EndBlockEvents...) + events, err := intoABCIEvents(allEvents, indexSet) + if err != nil { + return nil, err + } + + txResults, err := intoABCITxResults(in.TxResults, indexSet) + if err != nil { + return nil, err + } + resp := &abci.FinalizeBlockResponse{ - Events: intoABCIEvents(allEvents, indexSet), - TxResults: intoABCITxResults(in.TxResults, indexSet), + Events: events, + TxResults: txResults, ValidatorUpdates: intoABCIValidatorUpdates(in.ValidatorUpdates), AppHash: appHash, ConsensusParamUpdates: cp, @@ -97,7 +107,7 @@ func intoABCIValidatorUpdates(updates []appmodulev2.ValidatorUpdate) []abci.Vali return valsetUpdates } -func intoABCITxResults(results []server.TxResult, indexSet map[string]struct{}) []*abci.ExecTxResult { +func intoABCITxResults(results []server.TxResult, indexSet map[string]struct{}) ([]*abci.ExecTxResult, error) { res := make([]*abci.ExecTxResult, len(results)) for i := range results { if results[i].Error != nil { @@ -110,29 +120,36 @@ func intoABCITxResults(results []server.TxResult, indexSet map[string]struct{}) continue } - + events, err := intoABCIEvents(results[i].Events, indexSet) + if err != nil { + return nil, err + } res[i] = responseExecTxResultWithEvents( results[i].Error, results[i].GasWanted, results[i].GasUsed, - intoABCIEvents(results[i].Events, indexSet), + events, false, ) } - return res + return res, nil } -func intoABCIEvents(events []event.Event, indexSet map[string]struct{}) []abci.Event { +func intoABCIEvents(events []event.Event, indexSet map[string]struct{}) ([]abci.Event, error) { indexAll := len(indexSet) == 0 abciEvents := make([]abci.Event, len(events)) for i, e := range events { + attributes, err := e.Attributes() + if err != nil { + return nil, err + } abciEvents[i] = abci.Event{ Type: e.Type, - Attributes: make([]abci.EventAttribute, len(e.Attributes)), + Attributes: make([]abci.EventAttribute, len(attributes)), } - for j, attr := range e.Attributes { + for j, attr := range attributes { _, index := indexSet[fmt.Sprintf("%s.%s", e.Type, attr.Key)] abciEvents[i].Attributes[j] = abci.EventAttribute{ Key: attr.Key, @@ -141,19 +158,23 @@ func intoABCIEvents(events []event.Event, indexSet map[string]struct{}) []abci.E } } } - return abciEvents + return abciEvents, nil } func intoABCISimulationResponse(txRes server.TxResult, indexSet map[string]struct{}) ([]byte, error) { indexAll := len(indexSet) == 0 abciEvents := make([]abci.Event, len(txRes.Events)) for i, e := range txRes.Events { + attributes, err := e.Attributes() + if err != nil { + return nil, err + } abciEvents[i] = abci.Event{ Type: e.Type, - Attributes: make([]abci.EventAttribute, len(e.Attributes)), + Attributes: make([]abci.EventAttribute, len(attributes)), } - for j, attr := range e.Attributes { + for j, attr := range attributes { _, index := indexSet[fmt.Sprintf("%s.%s", e.Type, attr.Key)] abciEvents[i].Attributes[j] = abci.EventAttribute{ Key: attr.Key, diff --git a/server/v2/commands.go b/server/v2/commands.go index 8651074f406f..da8e0ec6e537 100644 --- a/server/v2/commands.go +++ b/server/v2/commands.go @@ -38,14 +38,14 @@ func AddCommands[T transaction.Tx]( rootCmd *cobra.Command, newApp AppCreator[T], logger log.Logger, - serverCfg ServerConfig, + globalServerCfg ServerConfig, components ...ServerComponent[T], ) error { if len(components) == 0 { return errors.New("no components provided") } - server := NewServer(logger, serverCfg, components...) + server := NewServer(logger, globalServerCfg, components...) originalPersistentPreRunE := rootCmd.PersistentPreRunE rootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { // set the default command outputs diff --git a/server/v2/config_test.go b/server/v2/config_test.go index 6577b81192fb..f69e2ed56769 100644 --- a/server/v2/config_test.go +++ b/server/v2/config_test.go @@ -20,8 +20,8 @@ func TestReadConfig(t *testing.T) { v, err := serverv2.ReadConfig(configPath) require.NoError(t, err) - require.Equal(t, v.GetString("grpc.address"), grpc.DefaultConfig().Address) - require.Equal(t, v.GetString("store.app-db-backend"), store.DefaultConfig().AppDBBackend) + require.Equal(t, v.GetString(grpc.FlagAddress), grpc.DefaultConfig().Address) + require.Equal(t, v.GetString(store.FlagAppDBBackend), store.DefaultConfig().AppDBBackend) } func TestUnmarshalSubConfig(t *testing.T) { diff --git a/server/v2/go.mod b/server/v2/go.mod index dbb1d151c343..ebc615b582f3 100644 --- a/server/v2/go.mod +++ b/server/v2/go.mod @@ -14,7 +14,7 @@ replace ( require ( cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/log v1.4.1 cosmossdk.io/server/v2/appmanager v0.0.0-00010101000000-000000000000 @@ -30,7 +30,7 @@ require ( github.com/hashicorp/go-plugin v1.6.1 github.com/mitchellh/mapstructure v1.5.0 github.com/pelletier/go-toml/v2 v2.2.2 - github.com/prometheus/client_golang v1.20.3 + github.com/prometheus/client_golang v1.20.4 github.com/prometheus/common v0.59.1 github.com/rs/zerolog v1.33.0 github.com/spf13/cobra v1.8.1 @@ -44,6 +44,7 @@ require ( require ( cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 // indirect + cosmossdk.io/schema v0.3.0 // indirect github.com/DataDog/datadog-go v4.8.3+incompatible // indirect github.com/DataDog/zstd v1.5.5 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect diff --git a/server/v2/go.sum b/server/v2/go.sum index 5c55e95c520e..f9244688217f 100644 --- a/server/v2/go.sum +++ b/server/v2/go.sum @@ -1,11 +1,13 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 h1:IQNdY2kB+k+1OM2DvqFG1+UgeU1JzZrWtwuWzI3ZfwA= cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5/go.mod h1:0CuYKkFHxc1vw2JC+t21THBCALJVROrWVR/3PQ1urpc= cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= @@ -256,8 +258,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/server/v2/server.go b/server/v2/server.go index d1062618ab60..7ee91e649982 100644 --- a/server/v2/server.go +++ b/server/v2/server.go @@ -89,7 +89,6 @@ func (s *Server[T]) Start(ctx context.Context) error { g, ctx := errgroup.WithContext(ctx) for _, mod := range s.components { - mod := mod g.Go(func() error { return mod.Start(ctx) }) @@ -110,7 +109,6 @@ func (s *Server[T]) Stop(ctx context.Context) error { g, ctx := errgroup.WithContext(ctx) for _, mod := range s.components { - mod := mod g.Go(func() error { return mod.Stop(ctx) }) @@ -198,7 +196,6 @@ func (s *Server[T]) Init(appI AppI[T], cfg map[string]any, logger log.Logger) er var components []ServerComponent[T] for _, mod := range s.components { - mod := mod if err := mod.Init(appI, cfg, logger); err != nil { return err } diff --git a/server/v2/stf/core_event_service.go b/server/v2/stf/core_event_service.go index 7a294fc77960..9f9b48080cae 100644 --- a/server/v2/stf/core_event_service.go +++ b/server/v2/stf/core_event_service.go @@ -81,6 +81,6 @@ func TypedEventToEvent(tev transaction.Msg) (event.Event, error) { return event.Event{ Type: evtType, - Attributes: attrs, + Attributes: func() ([]event.Attribute, error) { return attrs, nil }, }, nil } diff --git a/server/v2/stf/go.mod b/server/v2/stf/go.mod index 86eaec4d343a..b6de9d6002d8 100644 --- a/server/v2/stf/go.mod +++ b/server/v2/stf/go.mod @@ -3,7 +3,8 @@ module cosmossdk.io/server/v2/stf go 1.23 require ( - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 + cosmossdk.io/schema v0.3.0 github.com/cosmos/gogoproto v1.7.0 github.com/tidwall/btree v1.7.0 ) diff --git a/server/v2/stf/go.sum b/server/v2/stf/go.sum index 4fda4ea50d7d..3517a521d31c 100644 --- a/server/v2/stf/go.sum +++ b/server/v2/stf/go.sum @@ -1,5 +1,7 @@ -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= diff --git a/server/v2/stf/stf.go b/server/v2/stf/stf.go index e32a8f33293e..7907f99a75d3 100644 --- a/server/v2/stf/stf.go +++ b/server/v2/stf/stf.go @@ -15,6 +15,7 @@ import ( "cosmossdk.io/core/server" "cosmossdk.io/core/store" "cosmossdk.io/core/transaction" + "cosmossdk.io/schema/appdata" stfgas "cosmossdk.io/server/v2/stf/gas" "cosmossdk.io/server/v2/stf/internal" ) @@ -338,11 +339,8 @@ func (s STF[T]) preBlock( return nil, err } - for i, e := range ctx.events { - ctx.events[i].Attributes = append( - e.Attributes, - event.Attribute{Key: "mode", Value: "PreBlock"}, - ) + for i := range ctx.events { + ctx.events[i].BlockStage = appdata.PreBlockStage } return ctx.events, nil @@ -357,11 +355,8 @@ func (s STF[T]) beginBlock( return nil, err } - for i, e := range ctx.events { - ctx.events[i].Attributes = append( - e.Attributes, - event.Attribute{Key: "mode", Value: "BeginBlock"}, - ) + for i := range ctx.events { + ctx.events[i].BlockStage = appdata.BeginBlockStage } return ctx.events, nil @@ -383,11 +378,8 @@ func (s STF[T]) endBlock( ctx.events = append(ctx.events, events...) - for i, e := range ctx.events { - ctx.events[i].Attributes = append( - e.Attributes, - event.Attribute{Key: "mode", Value: "BeginBlock"}, - ) + for i := range ctx.events { + ctx.events[i].BlockStage = appdata.EndBlockStage } return ctx.events, valsetUpdates, nil diff --git a/server/v2/store/commands.go b/server/v2/store/commands.go index 5de696a8d307..7c50995f923e 100644 --- a/server/v2/store/commands.go +++ b/server/v2/store/commands.go @@ -91,7 +91,7 @@ func createRootStore(cmd *cobra.Command, v *viper.Viper, logger log.Logger) (sto } dbType = db.DBType(dbStr) } else { - dbType = db.DBType(v.GetString("store.app-db-backend")) + dbType = db.DBType(v.GetString(FlagAppDBBackend)) } scRawDb, err := db.NewDB(dbType, "application", filepath.Join(rootDir, "data"), nil) if err != nil { diff --git a/server/v2/store/flags.go b/server/v2/store/flags.go index 19b917a9d9ee..817a53c1b244 100644 --- a/server/v2/store/flags.go +++ b/server/v2/store/flags.go @@ -1,7 +1,16 @@ package store -const ( - FlagAppDBBackend = "app-db-backend" - FlagKeepRecent = "keep-recent" - FlagInterval = "interval" +import "fmt" + +// start flags are prefixed with the server name +// as the config in prefixed with the server name +// this allows viper to properly bind the flags +func prefix(f string) string { + return fmt.Sprintf("%s.%s", ServerName, f) +} + +var ( + FlagAppDBBackend = prefix("app-db-backend") + FlagKeepRecent = prefix("keep-recent") + FlagInterval = prefix("interval") ) diff --git a/server/v2/store/server.go b/server/v2/store/server.go index e16a09137a4b..a5f464c964a5 100644 --- a/server/v2/store/server.go +++ b/server/v2/store/server.go @@ -11,6 +11,14 @@ import ( serverv2 "cosmossdk.io/server/v2" ) +var ( + _ serverv2.ServerComponent[transaction.Tx] = (*StoreComponent[transaction.Tx])(nil) + _ serverv2.HasConfig = (*StoreComponent[transaction.Tx])(nil) + _ serverv2.HasCLICommands = (*StoreComponent[transaction.Tx])(nil) +) + +const ServerName = "store" + // StoreComponent manages store config // and contains prune & snapshot commands type StoreComponent[T transaction.Tx] struct { @@ -35,7 +43,7 @@ func (s *StoreComponent[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logg } func (s *StoreComponent[T]) Name() string { - return "store" + return ServerName } func (s *StoreComponent[T]) Start(ctx context.Context) error { diff --git a/server/v2/streaming/utils.go b/server/v2/streaming/utils.go index 658f2e978d4b..0266d5526b3c 100644 --- a/server/v2/streaming/utils.go +++ b/server/v2/streaming/utils.go @@ -2,15 +2,18 @@ package streaming import "cosmossdk.io/core/event" -func IntoStreamingEvents(events []event.Event) []*Event { +func IntoStreamingEvents(events []event.Event) ([]*Event, error) { streamingEvents := make([]*Event, len(events)) for _, event := range events { strEvent := &Event{ Type: event.Type, } - - for _, eventValue := range event.Attributes { + attrs, err := event.Attributes() + if err != nil { + return nil, err + } + for _, eventValue := range attrs { strEvent.Attributes = append(strEvent.Attributes, &EventAttribute{ Key: eventValue.Key, Value: eventValue.Value, @@ -19,5 +22,5 @@ func IntoStreamingEvents(events []event.Event) []*Event { streamingEvents = append(streamingEvents, strEvent) } - return streamingEvents + return streamingEvents, nil } diff --git a/server/v2/types.go b/server/v2/types.go index f25dbb8ab388..afa82969131a 100644 --- a/server/v2/types.go +++ b/server/v2/types.go @@ -16,7 +16,6 @@ type AppI[T transaction.Tx] interface { Name() string InterfaceRegistry() server.InterfaceRegistry GetAppManager() *appmanager.AppManager[T] - GetConsensusAuthority() string // TODO remove GetGPRCMethodsToMessageMap() map[string]func() gogoproto.Message GetStore() any } diff --git a/simapp/app.go b/simapp/app.go index 00f27cacb87e..1127b73b8acf 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -11,6 +11,8 @@ import ( "path/filepath" abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" + cmtcrypto "github.com/cometbft/cometbft/crypto" + cmted25519 "github.com/cometbft/cometbft/crypto/ed25519" "github.com/cosmos/gogoproto/proto" "github.com/spf13/cast" @@ -183,7 +185,7 @@ type SimApp struct { sm *module.SimulationManager // module configurator - configurator module.Configurator // nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. + configurator module.Configurator //nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. } func init() { @@ -463,15 +465,15 @@ func NewSimApp( auth.NewAppModule(appCodec, app.AuthKeeper, app.AccountsKeeper, authsims.RandomGenesisAccounts, nil), vesting.NewAppModule(app.AuthKeeper, app.BankKeeper), bank.NewAppModule(appCodec, app.BankKeeper, app.AuthKeeper), - feegrantmodule.NewAppModule(appCodec, app.AuthKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), + feegrantmodule.NewAppModule(appCodec, app.FeeGrantKeeper, app.interfaceRegistry), gov.NewAppModule(appCodec, &app.GovKeeper, app.AuthKeeper, app.BankKeeper, app.PoolKeeper), mint.NewAppModule(appCodec, app.MintKeeper, app.AuthKeeper, nil), slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AuthKeeper, app.BankKeeper, app.StakingKeeper, app.interfaceRegistry, cometService), - distr.NewAppModule(appCodec, app.DistrKeeper, app.AuthKeeper, app.BankKeeper, app.StakingKeeper), - staking.NewAppModule(appCodec, app.StakingKeeper, app.AuthKeeper, app.BankKeeper), + distr.NewAppModule(appCodec, app.DistrKeeper, app.StakingKeeper), + staking.NewAppModule(appCodec, app.StakingKeeper), upgrade.NewAppModule(app.UpgradeKeeper), evidence.NewAppModule(appCodec, app.EvidenceKeeper, cometService), - authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AuthKeeper, app.BankKeeper, app.interfaceRegistry), + authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.interfaceRegistry), groupmodule.NewAppModule(appCodec, app.GroupKeeper, app.AuthKeeper, app.BankKeeper, app.interfaceRegistry), nftmodule.NewAppModule(appCodec, app.NFTKeeper, app.AuthKeeper, app.BankKeeper, app.interfaceRegistry), consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper), @@ -705,7 +707,7 @@ func (app *SimApp) EndBlocker(ctx sdk.Context) (sdk.EndBlock, error) { return app.ModuleManager.EndBlock(ctx) } -func (a *SimApp) Configurator() module.Configurator { // nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. +func (a *SimApp) Configurator() module.Configurator { //nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. return a.configurator } @@ -831,6 +833,14 @@ func (app *SimApp) RegisterNodeService(clientCtx client.Context, cfg config.Conf nodeservice.RegisterNodeService(clientCtx, app.GRPCQueryRouter(), cfg) } +// ValidatorKeyProvider returns a function that generates a validator key +// Supported key types are those supported by Comet: ed25519, secp256k1, bls12-381 +func (app *SimApp) ValidatorKeyProvider() runtime.KeyGenF { + return func() (cmtcrypto.PrivKey, error) { + return cmted25519.GenPrivKey(), nil + } +} + // GetMaccPerms returns a copy of the module account permissions // // NOTE: This is solely to be used for testing purposes. diff --git a/simapp/genesis_account_test.go b/simapp/genesis_account_test.go index d813e9ec7e31..eccb8cc66c6e 100644 --- a/simapp/genesis_account_test.go +++ b/simapp/genesis_account_test.go @@ -81,7 +81,6 @@ func TestSimGenesisAccountValidate(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { require.Equal(t, tc.wantErr, tc.sga.Validate() != nil) }) diff --git a/simapp/go.mod b/simapp/go.mod index 526905f0f11e..8db7cd0cbea4 100644 --- a/simapp/go.mod +++ b/simapp/go.mod @@ -6,14 +6,14 @@ require ( cosmossdk.io/api v0.7.5 cosmossdk.io/client/v2 v2.0.0-20230630094428-02b760776860 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/depinject v1.0.0 cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc cosmossdk.io/tools/confix v0.0.0-20230613133644-0a778132a60f - cosmossdk.io/x/accounts v0.0.0-20240226161501-23359a0b6d91 + cosmossdk.io/x/accounts v0.0.0-20240913065641-0064ccbce64e cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 cosmossdk.io/x/authz v0.0.0-00010101000000-000000000000 cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 @@ -47,7 +47,10 @@ require ( google.golang.org/protobuf v1.34.2 ) -require google.golang.org/grpc v1.66.2 +require ( + cosmossdk.io/x/accounts/defaults/base v0.0.0-00010101000000-000000000000 + google.golang.org/grpc v1.66.2 +) require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect @@ -59,7 +62,7 @@ require ( cloud.google.com/go/iam v1.1.13 // indirect cloud.google.com/go/storage v1.43.0 // indirect cosmossdk.io/errors v1.0.1 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/x/accounts/defaults/multisig v0.0.0-00010101000000-000000000000 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect @@ -174,7 +177,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -244,6 +247,7 @@ replace ( cosmossdk.io/store => ../store cosmossdk.io/tools/confix => ../tools/confix cosmossdk.io/x/accounts => ../x/accounts + cosmossdk.io/x/accounts/defaults/base => ../x/accounts/defaults/base cosmossdk.io/x/accounts/defaults/lockup => ../x/accounts/defaults/lockup cosmossdk.io/x/accounts/defaults/multisig => ../x/accounts/defaults/multisig cosmossdk.io/x/authz => ../x/authz diff --git a/simapp/go.sum b/simapp/go.sum index f823b8f23e9f..00a527347ae1 100644 --- a/simapp/go.sum +++ b/simapp/go.sum @@ -192,8 +192,8 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -202,8 +202,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= @@ -719,8 +719,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/simapp/sim_bench_test.go b/simapp/sim_bench_test.go index ba5f02652ef5..cf1361aaf299 100644 --- a/simapp/sim_bench_test.go +++ b/simapp/sim_bench_test.go @@ -3,92 +3,19 @@ package simapp import ( - "os" + "github.com/cosmos/cosmos-sdk/simsx" "testing" - flag "github.com/spf13/pflag" - "github.com/spf13/viper" - "github.com/stretchr/testify/require" - - "cosmossdk.io/log" - - "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/server" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - "github.com/cosmos/cosmos-sdk/testutils/sims" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" ) -var FlagEnableBenchStreamingValue bool - -// Get flags every time the simulator is run -func init() { - flag.BoolVar(&FlagEnableBenchStreamingValue, "EnableStreaming", false, "Enable streaming service") -} - // Profile with: // /usr/local/go/bin/go test -benchmem -run=^$ cosmossdk.io/simapp -bench ^BenchmarkFullAppSimulation$ -Commit=true -cpuprofile cpu.out func BenchmarkFullAppSimulation(b *testing.B) { b.ReportAllocs() config := simcli.NewConfigFromFlags() - config.ChainID = sims.SimAppChainID - - db, dir, logger, skip, err := simtestutil.SetupSimulation(config, "goleveldb-app-sim", "Simulation", simcli.FlagVerboseValue, simcli.FlagEnabledValue) - if err != nil { - b.Fatalf("simulation setup failed: %s", err.Error()) - } - - if skip { - b.Skip("skipping benchmark application simulation") - } - - defer func() { - require.NoError(b, db.Close()) - require.NoError(b, os.RemoveAll(dir)) - }() - - appOptions := viper.New() - appOptions.SetDefault(flags.FlagHome, DefaultNodeHome) - appOptions.SetDefault(server.FlagInvCheckPeriod, simcli.FlagPeriodValue) - - app := NewSimApp(logger, db, nil, true, appOptions, interBlockCacheOpt(), baseapp.SetChainID(sims.SimAppChainID)) - - blockedAddrs, err := BlockedAddresses(app.InterfaceRegistry().SigningContext().AddressCodec()) - require.NoError(b, err) - - // run randomized simulation - simParams, simErr := simulation.SimulateFromSeedX( - b, - log.NewNopLogger(), - os.Stdout, - app.BaseApp, - simtestutil.AppStateFn(app.AppCodec(), app.AuthKeeper.AddressCodec(), app.StakingKeeper.ValidatorAddressCodec(), app.SimulationManager(), app.DefaultGenesis()), - simtypes.RandomAccounts, - simtestutil.SimulationOperations(app, app.AppCodec(), config, app.txConfig), - blockedAddrs, - config, - app.AppCodec(), - app.txConfig.SigningContext().AddressCodec(), - &simulation.DummyLogWriter{}, - ) - - // export state and simParams before the simulation error is checked - if err = simtestutil.CheckExportSimulation(app, config, simParams); err != nil { - b.Fatal(err) - } - - if simErr != nil { - b.Fatal(simErr) - } + config.ChainID = simsx.SimAppChainID - if config.Commit { - db, ok := db.(simtestutil.DBStatsInterface) - if ok { - simtestutil.PrintStats(db) - } - } + simsx.RunWithSeed(b, config, NewSimApp, setupStateFactory, 1, nil) } diff --git a/simapp/sim_test.go b/simapp/sim_test.go index 9cb61c051adf..0fa1a5a472ca 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -11,6 +11,12 @@ import ( "strings" "sync" "testing" + "time" + + abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" corestore "cosmossdk.io/core/store" "cosmossdk.io/log" @@ -20,18 +26,15 @@ import ( "cosmossdk.io/x/feegrant" slashingtypes "cosmossdk.io/x/slashing/types" stakingtypes "cosmossdk.io/x/staking/types" - abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" - cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + "github.com/cosmos/cosmos-sdk/baseapp" servertypes "github.com/cosmos/cosmos-sdk/server/types" + "github.com/cosmos/cosmos-sdk/simsx" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - "github.com/cosmos/cosmos-sdk/testutils/sims" sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/simulation" simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) // SimAppChainID hardcoded chainID for simulation @@ -51,32 +54,34 @@ func interBlockCacheOpt() func(*baseapp.BaseApp) { } func TestFullAppSimulation(t *testing.T) { - sims.Run(t, NewSimApp, setupStateFactory) + simsx.Run(t, NewSimApp, setupStateFactory) } -func setupStateFactory(app *SimApp) sims.SimStateFactory { +func setupStateFactory(app *SimApp) simsx.SimStateFactory { blockedAddre, _ := BlockedAddresses(app.interfaceRegistry.SigningContext().AddressCodec()) - return sims.SimStateFactory{ - Codec: app.AppCodec(), - AppStateFn: simtestutil.AppStateFn(app.AppCodec(), app.AuthKeeper.AddressCodec(), app.StakingKeeper.ValidatorAddressCodec(), app.SimulationManager(), app.DefaultGenesis()), - BlockedAddr: blockedAddre, + return simsx.SimStateFactory{ + Codec: app.AppCodec(), + AppStateFn: simtestutil.AppStateFn(app.AppCodec(), app.AuthKeeper.AddressCodec(), app.StakingKeeper.ValidatorAddressCodec(), app.SimulationManager().Modules, app.DefaultGenesis()), + BlockedAddr: blockedAddre, + AccountSource: app.AuthKeeper, + BalanceSource: app.BankKeeper, } } var ( - exportAllModules = []string{} - exportWithValidatorSet = []string{} + exportAllModules []string + exportWithValidatorSet []string ) func TestAppImportExport(t *testing.T) { - sims.Run(t, NewSimApp, setupStateFactory, func(t *testing.T, ti sims.TestInstance[*SimApp]) { + simsx.Run(t, NewSimApp, setupStateFactory, func(t testing.TB, ti simsx.TestInstance[*SimApp], _ []simtypes.Account) { app := ti.App t.Log("exporting genesis...\n") exported, err := app.ExportAppStateAndValidators(false, exportWithValidatorSet, exportAllModules) require.NoError(t, err) t.Log("importing genesis...\n") - newTestInstance := sims.NewSimulationAppInstance(t, ti.Cfg, NewSimApp) + newTestInstance := simsx.NewSimulationAppInstance(t, ti.Cfg, NewSimApp) newApp := newTestInstance.App var genesisState GenesisState require.NoError(t, json.Unmarshal(exported.AppState, &genesisState)) @@ -111,40 +116,40 @@ func TestAppImportExport(t *testing.T) { // set up a new node instance, Init chain from exported genesis // run new instance for n blocks func TestAppSimulationAfterImport(t *testing.T) { - sims.Run(t, NewSimApp, setupStateFactory, func(t *testing.T, ti sims.TestInstance[*SimApp]) { + simsx.Run(t, NewSimApp, setupStateFactory, func(t testing.TB, ti simsx.TestInstance[*SimApp], accs []simtypes.Account) { app := ti.App t.Log("exporting genesis...\n") exported, err := app.ExportAppStateAndValidators(false, exportWithValidatorSet, exportAllModules) require.NoError(t, err) - t.Log("importing genesis...\n") - newTestInstance := sims.NewSimulationAppInstance(t, ti.Cfg, NewSimApp) - newApp := newTestInstance.App - _, err = newApp.InitChain(&abci.InitChainRequest{ - AppStateBytes: exported.AppState, - ChainId: sims.SimAppChainID, - }) - if IsEmptyValidatorSetErr(err) { - t.Skip("Skipping simulation as all validators have been unbonded") - return + importGenesisStateFactory := func(app *SimApp) simsx.SimStateFactory { + return simsx.SimStateFactory{ + Codec: app.AppCodec(), + AppStateFn: func(r *rand.Rand, _ []simtypes.Account, config simtypes.Config) (json.RawMessage, []simtypes.Account, string, time.Time) { + t.Log("importing genesis...\n") + genesisTimestamp := time.Unix(config.GenesisTime, 0) + + _, err = app.InitChain(&abci.InitChainRequest{ + AppStateBytes: exported.AppState, + ChainId: simsx.SimAppChainID, + InitialHeight: exported.Height, + Time: genesisTimestamp, + }) + if IsEmptyValidatorSetErr(err) { + t.Skip("Skipping simulation as all validators have been unbonded") + return nil, nil, "", time.Time{} + } + require.NoError(t, err) + // use accounts from initial run + return exported.AppState, accs, config.ChainID, genesisTimestamp + }, + BlockedAddr: must(BlockedAddresses(app.AuthKeeper.AddressCodec())), + AccountSource: app.AuthKeeper, + BalanceSource: app.BankKeeper, + } } - require.NoError(t, err) - newStateFactory := setupStateFactory(newApp) - _, err = simulation.SimulateFromSeedX( - t, - newTestInstance.AppLogger, - sims.WriteToDebugLog(newTestInstance.AppLogger), - newApp.BaseApp, - newStateFactory.AppStateFn, - simtypes.RandomAccounts, - simtestutil.SimulationOperations(newApp, newApp.AppCodec(), newTestInstance.Cfg, newApp.TxConfig()), - newStateFactory.BlockedAddr, - newTestInstance.Cfg, - newStateFactory.Codec, - newApp.TxConfig().SigningContext().AddressCodec(), - ti.ExecLogWriter, - ) - require.NoError(t, err) + ti.Cfg.InitialBlockHeight = int(exported.Height) + simsx.RunWithSeed(t, ti.Cfg, NewSimApp, importGenesisStateFactory, ti.Cfg.Seed, ti.Cfg.FuzzSeed) }) } @@ -178,7 +183,7 @@ func TestAppStateDeterminism(t *testing.T) { "streaming.abci.stop-node-on-err": true, } others := appOpts - appOpts = sims.AppOptionsFn(func(k string) any { + appOpts = simsx.AppOptionsFn(func(k string) any { if v, ok := m[k]; ok { return v } @@ -190,7 +195,7 @@ func TestAppStateDeterminism(t *testing.T) { var mx sync.Mutex appHashResults := make(map[int64][][]byte) appSimLogger := make(map[int64][]simulation.LogWriter) - captureAndCheckHash := func(t *testing.T, ti sims.TestInstance[*SimApp]) { + captureAndCheckHash := func(t testing.TB, ti simsx.TestInstance[*SimApp], _ []simtypes.Account) { seed, appHash := ti.Cfg.Seed, ti.App.LastCommitID().Hash mx.Lock() otherHashes, execWriters := appHashResults[seed], appSimLogger[seed] @@ -216,7 +221,7 @@ func TestAppStateDeterminism(t *testing.T) { } } // run simulations - sims.RunWithSeeds(t, interBlockCachingAppFactory, setupStateFactory, seeds, []byte{}, captureAndCheckHash) + simsx.RunWithSeeds(t, interBlockCachingAppFactory, setupStateFactory, seeds, []byte{}, captureAndCheckHash) } type ComparableStoreApp interface { @@ -226,7 +231,7 @@ type ComparableStoreApp interface { GetStoreKeys() []storetypes.StoreKey } -func AssertEqualStores(t *testing.T, app ComparableStoreApp, newApp ComparableStoreApp, storeDecoders simtypes.StoreDecoderRegistry, skipPrefixes map[string][][]byte) { +func AssertEqualStores(t testing.TB, app, newApp ComparableStoreApp, storeDecoders simtypes.StoreDecoderRegistry, skipPrefixes map[string][][]byte) { ctxA := app.NewContextLegacy(true, cmtproto.Header{Height: app.LastBlockHeight()}) ctxB := newApp.NewContextLegacy(true, cmtproto.Header{Height: app.LastBlockHeight()}) @@ -264,7 +269,7 @@ func FuzzFullAppSimulation(f *testing.F) { t.Skip() return } - sims.RunWithSeeds( + simsx.RunWithSeeds( t, NewSimApp, setupStateFactory, @@ -273,3 +278,10 @@ func FuzzFullAppSimulation(f *testing.F) { ) }) } + +func must[T any](r T, err error) T { + if err != nil { + panic(err) + } + return r +} diff --git a/simapp/v2/app_config.go b/simapp/v2/app_config.go index 4f8b0bcb9088..99697b94af70 100644 --- a/simapp/v2/app_config.go +++ b/simapp/v2/app_config.go @@ -266,10 +266,8 @@ var ( Config: appconfig.WrapAny(&govmodulev1.Module{}), }, { - Name: consensustypes.ModuleName, - Config: appconfig.WrapAny(&consensusmodulev1.Module{ - Authority: "consensus", // TODO remove. - }), + Name: consensustypes.ModuleName, + Config: appconfig.WrapAny(&consensusmodulev1.Module{}), }, { Name: accounts.ModuleName, diff --git a/simapp/v2/app_di.go b/simapp/v2/app_di.go index 733ab1ffc829..3a3245627639 100644 --- a/simapp/v2/app_di.go +++ b/simapp/v2/app_di.go @@ -13,7 +13,6 @@ import ( "cosmossdk.io/log" "cosmossdk.io/runtime/v2" "cosmossdk.io/store/v2/root" - consensuskeeper "cosmossdk.io/x/consensus/keeper" upgradekeeper "cosmossdk.io/x/upgrade/keeper" "github.com/cosmos/cosmos-sdk/client" @@ -38,8 +37,7 @@ type SimApp[T transaction.Tx] struct { // required keepers during wiring // others keepers are all in the app - UpgradeKeeper *upgradekeeper.Keeper - ConsensusParamsKeeper consensuskeeper.Keeper + UpgradeKeeper *upgradekeeper.Keeper } func init() { @@ -135,7 +133,6 @@ func NewSimApp[T transaction.Tx]( &app.txConfig, &app.interfaceRegistry, &app.UpgradeKeeper, - &app.ConsensusParamsKeeper, ); err != nil { panic(err) } @@ -186,11 +183,6 @@ func (app *SimApp[T]) TxConfig() client.TxConfig { return app.txConfig } -// GetConsensusAuthority gets the consensus authority. -func (app *SimApp[T]) GetConsensusAuthority() string { - return app.ConsensusParamsKeeper.GetAuthority() -} - // GetStore gets the app store. func (app *SimApp[T]) GetStore() any { return app.App.GetStore() diff --git a/simapp/v2/app_test.go b/simapp/v2/app_test.go index a51354e4b3b6..f634d2d67664 100644 --- a/simapp/v2/app_test.go +++ b/simapp/v2/app_test.go @@ -20,6 +20,7 @@ import ( sdkmath "cosmossdk.io/math" serverv2 "cosmossdk.io/server/v2" comettypes "cosmossdk.io/server/v2/cometbft/types" + serverv2store "cosmossdk.io/server/v2/store" "cosmossdk.io/store/v2/db" banktypes "cosmossdk.io/x/bank/types" @@ -36,7 +37,7 @@ func NewTestApp(t *testing.T) (*SimApp[transaction.Tx], context.Context) { logger := log.NewTestLogger(t) vp := viper.New() - vp.Set("store.app-db-backend", string(db.DBTypeGoLevelDB)) + vp.Set(serverv2store.FlagAppDBBackend, string(db.DBTypeGoLevelDB)) vp.Set(serverv2.FlagHome, t.TempDir()) app := NewSimApp[transaction.Tx](logger, vp) diff --git a/simapp/v2/genesis_account_test.go b/simapp/v2/genesis_account_test.go index 5b8339b29c0b..d5f80a702b05 100644 --- a/simapp/v2/genesis_account_test.go +++ b/simapp/v2/genesis_account_test.go @@ -81,7 +81,6 @@ func TestSimGenesisAccountValidate(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { require.Equal(t, tc.wantErr, tc.sga.Validate() != nil) }) diff --git a/simapp/v2/go.mod b/simapp/v2/go.mod index e4003e4c9012..299c0fa6ec3f 100644 --- a/simapp/v2/go.mod +++ b/simapp/v2/go.mod @@ -5,7 +5,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 cosmossdk.io/client/v2 v2.0.0-00010101000000-000000000000 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/depinject v1.0.0 cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 @@ -14,7 +14,7 @@ require ( cosmossdk.io/server/v2/cometbft v0.0.0-00010101000000-000000000000 cosmossdk.io/store/v2 v2.0.0 cosmossdk.io/tools/confix v0.0.0-00010101000000-000000000000 - cosmossdk.io/x/accounts v0.0.0-20240226161501-23359a0b6d91 + cosmossdk.io/x/accounts v0.0.0-20240913065641-0064ccbce64e cosmossdk.io/x/authz v0.0.0-00010101000000-000000000000 cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 cosmossdk.io/x/circuit v0.0.0-20230613133644-0a778132a60f @@ -35,6 +35,7 @@ require ( github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect // this version is not used as it is always replaced by the latest Cosmos SDK version github.com/cosmos/cosmos-sdk v0.53.0 + github.com/spf13/cast v1.7.0 // indirect github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 @@ -55,10 +56,11 @@ require ( cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/server/v2/appmanager v0.0.0-20240802110823-cffeedff643d // indirect cosmossdk.io/server/v2/stf v0.0.0-20240708142107-25e99c54bac1 // indirect cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect + cosmossdk.io/x/accounts/defaults/base v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 // indirect cosmossdk.io/x/accounts/defaults/multisig v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.4 // indirect @@ -179,7 +181,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -193,7 +195,6 @@ require ( github.com/sasha-s/go-deadlock v0.3.5 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect - github.com/spf13/cast v1.7.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.13 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect @@ -248,6 +249,7 @@ replace ( cosmossdk.io/collections => ../../collections cosmossdk.io/tools/confix => ../../tools/confix cosmossdk.io/x/accounts => ../../x/accounts + cosmossdk.io/x/accounts/defaults/base => ../../x/accounts/defaults/base cosmossdk.io/x/accounts/defaults/lockup => ../../x/accounts/defaults/lockup cosmossdk.io/x/accounts/defaults/multisig => ../../x/accounts/defaults/multisig cosmossdk.io/x/authz => ../../x/authz diff --git a/simapp/v2/go.sum b/simapp/v2/go.sum index ede14d58a04e..65aa48935acf 100644 --- a/simapp/v2/go.sum +++ b/simapp/v2/go.sum @@ -192,8 +192,8 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -204,8 +204,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= @@ -723,8 +723,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/simapp/v2/simdv2/cmd/commands.go b/simapp/v2/simdv2/cmd/commands.go index d58619170e0d..916f4b2be9da 100644 --- a/simapp/v2/simdv2/cmd/commands.go +++ b/simapp/v2/simdv2/cmd/commands.go @@ -74,7 +74,11 @@ func initRootCmd[T transaction.Tx]( newApp, logger, initServerConfig(), - cometbft.New(&genericTxDecoder[T]{txConfig}, cometbft.DefaultServerOptions[T]()), + cometbft.New( + &genericTxDecoder[T]{txConfig}, + initCometOptions[T](), + initCometConfig(), + ), grpc.New[T](), store.New[T](newApp), ); err != nil { diff --git a/simapp/v2/simdv2/cmd/config.go b/simapp/v2/simdv2/cmd/config.go index c7f6b707c89c..51a7adb178e9 100644 --- a/simapp/v2/simdv2/cmd/config.go +++ b/simapp/v2/simdv2/cmd/config.go @@ -2,8 +2,13 @@ package cmd import ( "strings" + "time" + cmtcfg "github.com/cometbft/cometbft/config" + + "cosmossdk.io/core/transaction" serverv2 "cosmossdk.io/server/v2" + "cosmossdk.io/server/v2/cometbft" clientconfig "github.com/cosmos/cosmos-sdk/client/config" "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -68,3 +73,34 @@ func initServerConfig() serverv2.ServerConfig { return serverCfg } + +// initCometConfig helps to override default comet config template and configs. +func initCometConfig() cometbft.CfgOption { + cfg := cmtcfg.DefaultConfig() + + // display only warn logs by default except for p2p and state + cfg.LogLevel = "*:warn,p2p:info,state:info" + // increase block timeout + cfg.Consensus.TimeoutCommit = 5 * time.Second + // overwrite default pprof listen address + cfg.RPC.PprofListenAddress = "localhost:6060" + + return cometbft.OverwriteDefaultConfigTomlConfig(cfg) +} + +func initCometOptions[T transaction.Tx]() cometbft.ServerOptions[T] { + serverOptions := cometbft.DefaultServerOptions[T]() + + // overwrite app mempool, using max-txs option + // serverOptions.Mempool = func(cfg map[string]any) mempool.Mempool[T] { + // if maxTxs := cast.ToInt(cfg[cometbft.FlagMempoolMaxTxs]); maxTxs >= 0 { + // return sdkmempool.NewSenderNonceMempool( + // sdkmempool.SenderNonceMaxTxOpt(maxTxs), + // ) + // } + + // return mempool.NoOpMempool[T]{} + // } + + return serverOptions +} diff --git a/simsx/README.md b/simsx/README.md new file mode 100644 index 000000000000..3e2d9146ce42 --- /dev/null +++ b/simsx/README.md @@ -0,0 +1,47 @@ +# Simsx + +This package introduces some new helper types to simplify message construction for simulations (sims). The focus is on better dev UX for new message factories. +Technically, they are adapters that build upon the existing sims framework. + +## [Message factory](https://github.com/cosmos/cosmos-sdk/blob/main/simsx/msg_factory.go) + +Simple functions as factories for dedicated sdk.Msgs. They have access to the context, reporter and test data environment. For example: + +```go +func MsgSendFactory() simsx.SimMsgFactoryFn[*types.MsgSend] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgSend) { + from := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + to := testData.AnyAccount(reporter, simsx.ExcludeAccounts(from)) + coins := from.LiquidBalance().RandSubsetCoins(reporter, simsx.WithSendEnabledCoins()) + return []simsx.SimAccount{from}, types.NewMsgSend(from.AddressBech32, to.AddressBech32, coins) + } +} +``` + +## [Sims registry](https://github.com/cosmos/cosmos-sdk/blob/main/simsx/registry.go) + +A new helper to register message factories with a default weight value. They can be overwritten by a parameters file as before. The registry is passed to the AppModule type. For example: + +```go +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_send", 100), simulation.MsgSendFactory()) + reg.Add(weights.Get("msg_multisend", 10), simulation.MsgMultiSendFactory()) +} +``` + +## [Reporter](https://github.com/cosmos/cosmos-sdk/blob/main/simsx/reporter.go) + +The reporter is a flow control structure that can be used in message factories to skip execution at any point. The idea is similar to the testing.T Skip in Go stdlib. Internally, it converts skip, success and failure events to legacy sim messages. +The reporter also provides some capability to print an execution summary. +It is also used to interact with the test data environment to not have errors checked all the time. +Message factories may want to abort early via + +```go +if reporter.IsSkipped() { + return nil, nil +} +``` + +## [Test data environment](https://github.com/cosmos/cosmos-sdk/blob/main/simsx/environment.go) + +The test data environment provides simple access to accounts and other test data used in most message factories. It also encapsulates some app internals like bank keeper or address codec. diff --git a/simsx/common_test.go b/simsx/common_test.go new file mode 100644 index 000000000000..43fcd7d41860 --- /dev/null +++ b/simsx/common_test.go @@ -0,0 +1,161 @@ +package simsx + +import ( + "context" + "math/rand" + + "github.com/cosmos/gogoproto/proto" + + coretransaction "cosmossdk.io/core/transaction" + "cosmossdk.io/x/tx/signing" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/address" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/std" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/auth/tx" +) + +// SimAccountFixture testing only +func SimAccountFixture(mutators ...func(account *SimAccount)) SimAccount { + r := rand.New(rand.NewSource(1)) + acc := SimAccount{ + Account: simtypes.RandomAccounts(r, 1)[0], + } + acc.liquidBalance = NewSimsAccountBalance(&acc, r, sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 1_000_000_000))) + for _, mutator := range mutators { + mutator(&acc) + } + return acc +} + +// MemoryAccountSource testing only +func MemoryAccountSource(srcs ...SimAccount) AccountSourceFn { + accs := make(map[string]FakeAccountI, len(srcs)) + for _, src := range srcs { + accs[src.AddressBech32] = FakeAccountI{SimAccount: src, id: 1, seq: 2} + } + return func(ctx context.Context, addr sdk.AccAddress) sdk.AccountI { + return accs[addr.String()] + } +} + +// testing only +func txConfig() client.TxConfig { + ir := must(codectypes.NewInterfaceRegistryWithOptions(codectypes.InterfaceRegistryOptions{ + ProtoFiles: proto.HybridResolver, + SigningOptions: signing.Options{ + AddressCodec: address.NewBech32Codec("cosmos"), + ValidatorAddressCodec: address.NewBech32Codec("cosmosvaloper"), + }, + })) + std.RegisterInterfaces(ir) + ir.RegisterImplementations((*coretransaction.Msg)(nil), &testdata.TestMsg{}) + protoCodec := codec.NewProtoCodec(ir) + signingCtx := protoCodec.InterfaceRegistry().SigningContext() + return tx.NewTxConfig(protoCodec, signingCtx.AddressCodec(), signingCtx.ValidatorAddressCodec(), tx.DefaultSignModes) +} + +var _ AppEntrypoint = SimDeliverFn(nil) + +type ( + AppEntrypointFn = SimDeliverFn + SimDeliverFn func(_txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) +) + +func (m SimDeliverFn) SimDeliver(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) { + return m(txEncoder, tx) +} + +var _ AccountSource = AccountSourceFn(nil) + +type AccountSourceFn func(ctx context.Context, addr sdk.AccAddress) sdk.AccountI + +func (a AccountSourceFn) GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI { + return a(ctx, addr) +} + +var _ sdk.AccountI = &FakeAccountI{} + +type FakeAccountI struct { + SimAccount + id, seq uint64 +} + +func (m FakeAccountI) GetAddress() sdk.AccAddress { + return m.Address +} + +func (m FakeAccountI) GetPubKey() cryptotypes.PubKey { + return m.PubKey +} + +func (m FakeAccountI) GetAccountNumber() uint64 { + return m.id +} + +func (m FakeAccountI) GetSequence() uint64 { + return m.seq +} + +func (m FakeAccountI) Reset() { + panic("implement me") +} + +func (m FakeAccountI) String() string { + panic("implement me") +} + +func (m FakeAccountI) ProtoMessage() { + panic("implement me") +} + +func (m FakeAccountI) SetAddress(address sdk.AccAddress) error { + panic("implement me") +} + +func (m FakeAccountI) SetPubKey(key cryptotypes.PubKey) error { + panic("implement me") +} + +func (m FakeAccountI) SetAccountNumber(u uint64) error { + panic("implement me") +} + +func (m FakeAccountI) SetSequence(u uint64) error { + panic("implement me") +} + +var _ AccountSourceX = &MockAccountSourceX{} + +// MockAccountSourceX mock impl for testing only +type MockAccountSourceX struct { + GetAccountFn func(ctx context.Context, addr sdk.AccAddress) sdk.AccountI + GetModuleAddressFn func(moduleName string) sdk.AccAddress +} + +func (m MockAccountSourceX) GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI { + if m.GetAccountFn == nil { + panic("not expected to be called") + } + return m.GetAccountFn(ctx, addr) +} + +func (m MockAccountSourceX) GetModuleAddress(moduleName string) sdk.AccAddress { + if m.GetModuleAddressFn == nil { + panic("not expected to be called") + } + return m.GetModuleAddressFn(moduleName) +} + +func must[T any](r T, err error) T { + if err != nil { + panic(err) + } + return r +} diff --git a/simsx/context.go b/simsx/context.go new file mode 100644 index 000000000000..13bdc10efad3 --- /dev/null +++ b/simsx/context.go @@ -0,0 +1,17 @@ +package simsx + +import ( + "context" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// BlockTime read header block time from sdk context or sims context key if not present +func BlockTime(ctx context.Context) time.Time { + sdkCtx, ok := sdk.TryUnwrapSDKContext(ctx) + if ok { + return sdkCtx.BlockTime() + } + return ctx.Value("sims.header.time").(time.Time) +} diff --git a/simsx/delivery.go b/simsx/delivery.go new file mode 100644 index 000000000000..f67c9cc79b88 --- /dev/null +++ b/simsx/delivery.go @@ -0,0 +1,98 @@ +package simsx + +import ( + "context" + "errors" + "fmt" + "math/rand" + + "github.com/cosmos/cosmos-sdk/client" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +type ( + // AppEntrypoint is an alias to the simtype interface + AppEntrypoint = simtypes.AppEntrypoint + + AccountSource interface { + GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI + } + // SimDeliveryResultHandler processes the delivery response error. Some sims are supposed to fail and expect an error. + // An unhandled error returned indicates a failure + SimDeliveryResultHandler func(error) error +) + +// DeliverSimsMsg delivers a simulation message by creating and signing a mock transaction, +// then delivering it to the application through the specified entrypoint. It returns a legacy +// operation message representing the result of the delivery. +// +// The function takes the following parameters: +// - reporter: SimulationReporter - Interface for reporting the result of the delivery +// - r: *rand.Rand - Random number generator used for creating the mock transaction +// - app: AppEntrypoint - Entry point for delivering the simulation transaction to the application +// - txGen: client.TxConfig - Configuration for generating transactions +// - ak: AccountSource - Source for retrieving accounts +// - msg: sdk.Msg - The simulation message to be delivered +// - ctx: sdk.Context - The simulation context +// - chainID: string - The chain ID +// - senders: ...SimAccount - Accounts from which to send the simulation message +// +// The function returns a simtypes.OperationMsg, which is a legacy representation of the result +// of the delivery. +func DeliverSimsMsg( + ctx context.Context, + reporter SimulationReporter, + app AppEntrypoint, + r *rand.Rand, + txGen client.TxConfig, + ak AccountSource, + chainID string, + msg sdk.Msg, + deliveryResultHandler SimDeliveryResultHandler, + senders ...SimAccount, +) simtypes.OperationMsg { + if reporter.IsSkipped() { + return reporter.ToLegacyOperationMsg() + } + if len(senders) == 0 { + reporter.Fail(errors.New("no senders"), "encoding TX") + return reporter.ToLegacyOperationMsg() + } + accountNumbers := make([]uint64, len(senders)) + sequenceNumbers := make([]uint64, len(senders)) + for i := 0; i < len(senders); i++ { + acc := ak.GetAccount(ctx, senders[i].Address) + accountNumbers[i] = acc.GetAccountNumber() + sequenceNumbers[i] = acc.GetSequence() + } + fees := senders[0].LiquidBalance().RandFees() + tx, err := sims.GenSignedMockTx( + r, + txGen, + []sdk.Msg{msg}, + fees, + sims.DefaultGenTxGas, + chainID, + accountNumbers, + sequenceNumbers, + Collect(senders, func(a SimAccount) cryptotypes.PrivKey { return a.PrivKey })..., + ) + if err != nil { + reporter.Fail(err, "encoding TX") + return reporter.ToLegacyOperationMsg() + } + _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) + if err2 := deliveryResultHandler(err); err2 != nil { + var comment string + for _, msg := range tx.GetMsgs() { + comment += fmt.Sprintf("%#v", msg) + } + reporter.Fail(err2, fmt.Sprintf("delivering tx with msgs: %s", comment)) + return reporter.ToLegacyOperationMsg() + } + reporter.Success(msg) + return reporter.ToLegacyOperationMsg() +} diff --git a/simsx/delivery_test.go b/simsx/delivery_test.go new file mode 100644 index 000000000000..627841fcb9af --- /dev/null +++ b/simsx/delivery_test.go @@ -0,0 +1,74 @@ +package simsx + +import ( + "errors" + "math/rand" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +func TestDeliverSimsMsg(t *testing.T) { + var ( + sender = SimAccountFixture() + ak = MemoryAccountSource(sender) + myMsg = testdata.NewTestMsg(sender.Address) + txConfig = txConfig() + r = rand.New(rand.NewSource(1)) + ctx sdk.Context + ) + noopResultHandler := func(err error) error { return err } + specs := map[string]struct { + app AppEntrypoint + reporter func() SimulationReporter + deliveryResultHandler SimDeliveryResultHandler + errDeliveryResultHandler error + expOps simtypes.OperationMsg + }{ + "error when reporter skipped": { + app: SimDeliverFn(func(_txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) { + return sdk.GasInfo{GasWanted: 100, GasUsed: 20}, &sdk.Result{}, nil + }), + reporter: func() SimulationReporter { + r := NewBasicSimulationReporter() + r.Skip("testing") + return r + }, + expOps: simtypes.NoOpMsg("", "", "testing"), + }, + "successful delivery": { + app: SimDeliverFn(func(_txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) { + return sdk.GasInfo{GasWanted: 100, GasUsed: 20}, &sdk.Result{}, nil + }), + reporter: func() SimulationReporter { return NewBasicSimulationReporter() }, + deliveryResultHandler: noopResultHandler, + expOps: simtypes.NewOperationMsgBasic("", "", "", true), + }, + "error delivery": { + app: SimDeliverFn(func(_txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) { + return sdk.GasInfo{GasWanted: 100, GasUsed: 20}, &sdk.Result{}, errors.New("my error") + }), + reporter: func() SimulationReporter { return NewBasicSimulationReporter() }, + deliveryResultHandler: noopResultHandler, + expOps: simtypes.NewOperationMsgBasic("", "", "delivering tx with msgs: &testdata.TestMsg{Signers:[]string{\"cosmos1tnh2q55v8wyygtt9srz5safamzdengsnqeycj3\"}, DecField:0.000000000000000000}", false), + }, + "error delivery handled": { + app: SimDeliverFn(func(_txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) { + return sdk.GasInfo{GasWanted: 100, GasUsed: 20}, &sdk.Result{}, errors.New("my error") + }), + reporter: func() SimulationReporter { return NewBasicSimulationReporter() }, + deliveryResultHandler: func(err error) error { return nil }, + expOps: simtypes.NewOperationMsgBasic("", "", "", true), + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + got := DeliverSimsMsg(ctx, spec.reporter(), spec.app, r, txConfig, ak, "testing", myMsg, spec.deliveryResultHandler, sender) + assert.Equal(t, spec.expOps, got) + }) + } +} diff --git a/simsx/environment.go b/simsx/environment.go new file mode 100644 index 000000000000..e5302802cce4 --- /dev/null +++ b/simsx/environment.go @@ -0,0 +1,461 @@ +package simsx + +import ( + "context" + "errors" + "math/rand" + "slices" + "time" + + "cosmossdk.io/core/address" + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +// helper type for simple bank access +type contextAwareBalanceSource struct { + ctx context.Context + bank BalanceSource +} + +func (s contextAwareBalanceSource) SpendableCoins(accAddress sdk.AccAddress) sdk.Coins { + return s.bank.SpendableCoins(s.ctx, accAddress) +} + +func (s contextAwareBalanceSource) IsSendEnabledDenom(denom string) bool { + return s.bank.IsSendEnabledDenom(s.ctx, denom) +} + +// SimAccount is an extended simtypes.Account +type SimAccount struct { + simtypes.Account + r *rand.Rand + liquidBalance *SimsAccountBalance + bank contextAwareBalanceSource +} + +// LiquidBalance spendable balance. This excludes not spendable amounts like staked or vested amounts. +func (a *SimAccount) LiquidBalance() *SimsAccountBalance { + if a.liquidBalance == nil { + a.liquidBalance = NewSimsAccountBalance(a, a.r, a.bank.SpendableCoins(a.Address)) + } + return a.liquidBalance +} + +// SimsAccountBalance is a helper type for common access methods to balance amounts. +type SimsAccountBalance struct { + sdk.Coins + owner *SimAccount + r *rand.Rand +} + +// NewSimsAccountBalance constructor +func NewSimsAccountBalance(o *SimAccount, r *rand.Rand, coins sdk.Coins) *SimsAccountBalance { + return &SimsAccountBalance{Coins: coins, r: r, owner: o} +} + +type CoinsFilter interface { + Accept(c sdk.Coins) bool // returns false to reject +} +type CoinsFilterFn func(c sdk.Coins) bool + +func (f CoinsFilterFn) Accept(c sdk.Coins) bool { + return f(c) +} + +func WithSendEnabledCoins() CoinsFilter { + return statefulCoinsFilterFn(func(s *SimAccount, coins sdk.Coins) bool { + for _, coin := range coins { + if !s.bank.IsSendEnabledDenom(coin.Denom) { + return false + } + } + return true + }) +} + +// filter with context of SimAccount +type statefulCoinsFilter struct { + s *SimAccount + do func(s *SimAccount, c sdk.Coins) bool +} + +// constructor +func statefulCoinsFilterFn(f func(s *SimAccount, c sdk.Coins) bool) CoinsFilter { + return &statefulCoinsFilter{do: f} +} + +func (f statefulCoinsFilter) Accept(c sdk.Coins) bool { + if f.s == nil { + panic("account not set") + } + return f.do(f.s, c) +} + +func (f *statefulCoinsFilter) visit(s *SimAccount) { + f.s = s +} + +var _ visitable = &statefulCoinsFilter{} + +type visitable interface { + visit(s *SimAccount) +} + +// RandSubsetCoins return random amounts from the current balance. When the coins are empty, skip is called on the reporter. +// The amounts are removed from the liquid balance. +func (b *SimsAccountBalance) RandSubsetCoins(reporter SimulationReporter, filters ...CoinsFilter) sdk.Coins { + amount := b.randomAmount(5, reporter, b.Coins, filters...) + b.Coins = b.Coins.Sub(amount...) + if amount.Empty() { + reporter.Skip("got empty amounts") + } + return amount +} + +// RandSubsetCoin return random amount from the current balance. When the coins are empty, skip is called on the reporter. +// The amount is removed from the liquid balance. +func (b *SimsAccountBalance) RandSubsetCoin(reporter SimulationReporter, denom string, filters ...CoinsFilter) sdk.Coin { + ok, coin := b.Find(denom) + if !ok { + reporter.Skipf("no such coin: %s", denom) + return sdk.NewCoin(denom, math.ZeroInt()) + } + amounts := b.randomAmount(5, reporter, sdk.Coins{coin}, filters...) + if amounts.Empty() { + reporter.Skip("empty coin") + return sdk.NewCoin(denom, math.ZeroInt()) + } + b.BlockAmount(amounts[0]) + return amounts[0] +} + +// BlockAmount returns true when balance is > requested amount and subtracts the amount from the liquid balance +func (b *SimsAccountBalance) BlockAmount(amount sdk.Coin) bool { + ok, coin := b.Coins.Find(amount.Denom) + if !ok || !coin.IsPositive() || !coin.IsGTE(amount) { + return false + } + b.Coins = b.Coins.Sub(amount) + return true +} + +func (b *SimsAccountBalance) randomAmount(retryCount int, reporter SimulationReporter, coins sdk.Coins, filters ...CoinsFilter) sdk.Coins { + if retryCount < 0 || b.Coins.Empty() { + reporter.Skip("failed to find matching amount") + return sdk.Coins{} + } + amount := simtypes.RandSubsetCoins(b.r, coins) + for _, filter := range filters { + if f, ok := filter.(visitable); ok { + f.visit(b.owner) + } + if !filter.Accept(amount) { + return b.randomAmount(retryCount-1, reporter, coins, filters...) + } + } + return amount +} + +func (b *SimsAccountBalance) RandFees() sdk.Coins { + amount, err := simtypes.RandomFees(b.r, b.Coins) + if err != nil { + return sdk.Coins{} + } + return amount +} + +type SimAccountFilter interface { + // Accept returns true to accept the account or false to reject + Accept(a SimAccount) bool +} +type SimAccountFilterFn func(a SimAccount) bool + +func (s SimAccountFilterFn) Accept(a SimAccount) bool { + return s(a) +} + +func ExcludeAccounts(others ...SimAccount) SimAccountFilter { + return SimAccountFilterFn(func(a SimAccount) bool { + return !slices.ContainsFunc(others, func(o SimAccount) bool { + return a.Address.Equals(o.Address) + }) + }) +} + +// UniqueAccounts returns a stateful filter that rejects duplicate accounts. +// It uses a map to keep track of accounts that have been processed. +// If an account exists in the map, the filter function returns false +// to reject a duplicate, else it adds the account to the map and returns true. +// +// Example usage: +// +// uniqueAccountsFilter := simsx.UniqueAccounts() +// +// for { +// from := testData.AnyAccount(reporter, uniqueAccountsFilter) +// //... rest of the loop +// } +func UniqueAccounts() SimAccountFilter { + idx := make(map[string]struct{}) + return SimAccountFilterFn(func(a SimAccount) bool { + if _, ok := idx[a.AddressBech32]; ok { + return false + } + idx[a.AddressBech32] = struct{}{} + return true + }) +} + +func ExcludeAddresses(addrs ...string) SimAccountFilter { + return SimAccountFilterFn(func(a SimAccount) bool { + return !slices.Contains(addrs, a.AddressBech32) + }) +} + +func WithDenomBalance(denom string) SimAccountFilter { + return SimAccountFilterFn(func(a SimAccount) bool { + return a.LiquidBalance().AmountOf(denom).IsPositive() + }) +} + +func WithLiquidBalanceGTE(amount ...sdk.Coin) SimAccountFilter { + return SimAccountFilterFn(func(a SimAccount) bool { + return a.LiquidBalance().IsAllGTE(amount) + }) +} + +// WithSpendableBalance Filters for liquid token but send may not be enabled for all or any +func WithSpendableBalance() SimAccountFilter { + return SimAccountFilterFn(func(a SimAccount) bool { + return !a.LiquidBalance().Empty() + }) +} + +type ModuleAccountSource interface { + GetModuleAddress(moduleName string) sdk.AccAddress +} + +// BalanceSource is an interface for retrieving balance-related information for a given account. +type BalanceSource interface { + SpendableCoins(ctx context.Context, addr sdk.AccAddress) sdk.Coins + IsSendEnabledDenom(ctx context.Context, denom string) bool +} + +// ChainDataSource provides common sims test data and helper methods +type ChainDataSource struct { + r *rand.Rand + addressToAccountsPosIndex map[string]int + accounts []SimAccount + accountSource ModuleAccountSource + addressCodec address.Codec + bank contextAwareBalanceSource +} + +// NewChainDataSource constructor +func NewChainDataSource( + ctx context.Context, + r *rand.Rand, + ak ModuleAccountSource, + bk BalanceSource, + codec address.Codec, + oldSimAcc ...simtypes.Account, +) *ChainDataSource { + acc := make([]SimAccount, len(oldSimAcc)) + index := make(map[string]int, len(oldSimAcc)) + bank := contextAwareBalanceSource{ctx: ctx, bank: bk} + for i, a := range oldSimAcc { + acc[i] = SimAccount{Account: a, r: r, bank: bank} + index[a.AddressBech32] = i + if a.AddressBech32 == "" { + panic("test account has empty bech32 address") + } + } + return &ChainDataSource{ + r: r, + accountSource: ak, + addressCodec: codec, + accounts: acc, + bank: bank, + addressToAccountsPosIndex: index, + } +} + +// AnyAccount returns a random SimAccount matching the filter criteria. Module accounts are excluded. +// In case of an error or no matching account found, the reporter is set to skip and an empty value is returned. +func (c *ChainDataSource) AnyAccount(r SimulationReporter, filters ...SimAccountFilter) SimAccount { + acc := c.randomAccount(r, 5, filters...) + return acc +} + +// GetAccountbyAccAddr return SimAccount with given binary address. Reporter skip flag is set when not found. +func (c ChainDataSource) GetAccountbyAccAddr(reporter SimulationReporter, addr sdk.AccAddress) SimAccount { + if len(addr) == 0 { + reporter.Skip("can not find account for empty address") + return c.nullAccount() + } + addrStr, err := c.addressCodec.BytesToString(addr) + if err != nil { + reporter.Skipf("can not convert account address to string: %s", err) + return c.nullAccount() + } + return c.GetAccount(reporter, addrStr) +} + +func (c ChainDataSource) HasAccount(addr string) bool { + _, ok := c.addressToAccountsPosIndex[addr] + return ok +} + +// GetAccount return SimAccount with given bench32 address. Reporter skip flag is set when not found. +func (c ChainDataSource) GetAccount(reporter SimulationReporter, addr string) SimAccount { + pos, ok := c.addressToAccountsPosIndex[addr] + if !ok { + reporter.Skipf("no account: %s", addr) + return c.nullAccount() + } + return c.accounts[pos] +} + +func (c *ChainDataSource) randomAccount(reporter SimulationReporter, retryCount int, filters ...SimAccountFilter) SimAccount { + if retryCount < 0 { + reporter.Skip("failed to find a matching account") + return c.nullAccount() + } + idx := c.r.Intn(len(c.accounts)) + acc := c.accounts[idx] + for _, filter := range filters { + if !filter.Accept(acc) { + return c.randomAccount(reporter, retryCount-1, filters...) + } + } + return acc +} + +// create null object +func (c ChainDataSource) nullAccount() SimAccount { + return SimAccount{ + Account: simtypes.Account{}, + r: c.r, + liquidBalance: &SimsAccountBalance{}, + bank: c.accounts[0].bank, + } +} + +func (c *ChainDataSource) ModuleAccountAddress(reporter SimulationReporter, moduleName string) string { + acc := c.accountSource.GetModuleAddress(moduleName) + if acc == nil { + reporter.Skipf("unknown module account: %s", moduleName) + return "" + } + res, err := c.addressCodec.BytesToString(acc) + if err != nil { + reporter.Skipf("failed to encode module address: %s", err) + return "" + } + return res +} + +func (c *ChainDataSource) AddressCodec() address.Codec { + return c.addressCodec +} + +func (c *ChainDataSource) Rand() *XRand { + return &XRand{c.r} +} + +func (c *ChainDataSource) IsSendEnabledDenom(denom string) bool { + return c.bank.IsSendEnabledDenom(denom) +} + +// AllAccounts returns all accounts in legacy format +func (c *ChainDataSource) AllAccounts() []simtypes.Account { + return Collect(c.accounts, func(a SimAccount) simtypes.Account { return a.Account }) +} + +func (c *ChainDataSource) AccountsCount() int { + return len(c.accounts) +} + +// AccountAt return SimAccount within the accounts slice. Reporter skip flag is set when boundaries are exceeded. + +func (c *ChainDataSource) AccountAt(reporter SimulationReporter, i int) SimAccount { + if i > len(c.accounts) { + reporter.Skipf("account index out of range: %d", i) + return c.nullAccount() + } + return c.accounts[i] +} + +type XRand struct { + *rand.Rand +} + +// NewXRand constructor +func NewXRand(rand *rand.Rand) *XRand { + return &XRand{Rand: rand} +} + +func (r *XRand) StringN(max int) string { + return simtypes.RandStringOfLength(r.Rand, max) +} + +func (r *XRand) SubsetCoins(src sdk.Coins) sdk.Coins { + return simtypes.RandSubsetCoins(r.Rand, src) +} + +// Coin return one coin from the list +func (r *XRand) Coin(src sdk.Coins) sdk.Coin { + return src[r.Intn(len(src))] +} + +func (r *XRand) DecN(max math.LegacyDec) math.LegacyDec { + return simtypes.RandomDecAmount(r.Rand, max) +} + +func (r *XRand) IntInRange(min, max int) int { + return r.Rand.Intn(max-min) + min +} + +// Uint64InRange returns a pseudo-random uint64 number in the range [min, max]. +// It panics when min >= max +func (r *XRand) Uint64InRange(min, max uint64) uint64 { + return uint64(r.Rand.Int63n(int64(max-min)) + int64(min)) +} + +// Uint32InRange returns a pseudo-random uint32 number in the range [min, max]. +// It panics when min >= max +func (r *XRand) Uint32InRange(min, max uint32) uint32 { + return uint32(r.Rand.Intn(int(max-min))) + min +} + +func (r *XRand) PositiveSDKIntn(max math.Int) (math.Int, error) { + return simtypes.RandPositiveInt(r.Rand, max) +} + +func (r *XRand) PositiveSDKIntInRange(min, max math.Int) (math.Int, error) { + diff := max.Sub(min) + if !diff.IsPositive() { + return math.Int{}, errors.New("min value must not be greater or equal to max") + } + result, err := r.PositiveSDKIntn(diff) + if err != nil { + return math.Int{}, err + } + return result.Add(min), nil +} + +// Timestamp returns a timestamp between Jan 1, 2062 and Jan 1, 2262 +func (r *XRand) Timestamp() time.Time { + return simtypes.RandTimestamp(r.Rand) +} + +func (r *XRand) Bool() bool { + return r.Intn(100) > 50 +} + +func (r *XRand) Amount(balance math.Int) math.Int { + return simtypes.RandomAmount(r.Rand, balance) +} diff --git a/simsx/environment_test.go b/simsx/environment_test.go new file mode 100644 index 000000000000..957601326b23 --- /dev/null +++ b/simsx/environment_test.go @@ -0,0 +1,67 @@ +package simsx + +import ( + "math/rand" + "testing" + + "github.com/stretchr/testify/assert" + + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +func TestChainDataSourceAnyAccount(t *testing.T) { + codec := txConfig().SigningContext().AddressCodec() + r := rand.New(rand.NewSource(1)) + accs := simtypes.RandomAccounts(r, 3) + specs := map[string]struct { + filters []SimAccountFilter + assert func(t *testing.T, got SimAccount, reporter SimulationReporter) + }{ + "no filters": { + assert: func(t *testing.T, got SimAccount, reporter SimulationReporter) { //nolint:thelper // not a helper + assert.NotEmpty(t, got.AddressBech32) + assert.False(t, reporter.IsSkipped()) + }, + }, + "filter": { + filters: []SimAccountFilter{SimAccountFilterFn(func(a SimAccount) bool { return a.AddressBech32 == accs[2].AddressBech32 })}, + assert: func(t *testing.T, got SimAccount, reporter SimulationReporter) { //nolint:thelper // not a helper + assert.Equal(t, accs[2].AddressBech32, got.AddressBech32) + assert.False(t, reporter.IsSkipped()) + }, + }, + "no match": { + filters: []SimAccountFilter{SimAccountFilterFn(func(a SimAccount) bool { return false })}, + assert: func(t *testing.T, got SimAccount, reporter SimulationReporter) { //nolint:thelper // not a helper + assert.Empty(t, got.AddressBech32) + assert.True(t, reporter.IsSkipped()) + }, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + reporter := NewBasicSimulationReporter() + c := NewChainDataSource(sdk.Context{}, r, nil, nil, codec, accs...) + a := c.AnyAccount(reporter, spec.filters...) + spec.assert(t, a, reporter) + }) + } +} + +func TestChainDataSourceGetHasAccount(t *testing.T) { + codec := txConfig().SigningContext().AddressCodec() + r := rand.New(rand.NewSource(1)) + accs := simtypes.RandomAccounts(r, 3) + reporter := NewBasicSimulationReporter() + c := NewChainDataSource(sdk.Context{}, r, nil, nil, codec, accs...) + exisingAddr := accs[0].AddressBech32 + assert.Equal(t, exisingAddr, c.GetAccount(reporter, exisingAddr).AddressBech32) + assert.False(t, reporter.IsSkipped()) + assert.True(t, c.HasAccount(exisingAddr)) + // and non-existing account + reporter = NewBasicSimulationReporter() + assert.Empty(t, c.GetAccount(reporter, "non-existing").AddressBech32) + assert.False(t, c.HasAccount("non-existing")) + assert.True(t, reporter.IsSkipped()) +} diff --git a/simsx/msg_factory.go b/simsx/msg_factory.go new file mode 100644 index 000000000000..1c6b6e4b9611 --- /dev/null +++ b/simsx/msg_factory.go @@ -0,0 +1,179 @@ +package simsx + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// SimMsgFactoryX is an interface for creating and handling fuzz test-like simulation messages in the system. +type SimMsgFactoryX interface { + // MsgType returns an empty instance of the concrete message type that the factory provides. + // This instance is primarily used for deduplication and reporting purposes. + // The result must not be nil + MsgType() sdk.Msg + + // Create returns a FactoryMethod implementation which is responsible for constructing new instances of the message + // on each invocation. + Create() FactoryMethod + + // DeliveryResultHandler returns a SimDeliveryResultHandler instance which processes the delivery + // response error object. While most simulation factories anticipate successful message delivery, + // certain factories employ this handler to validate execution errors, thereby covering negative + // test scenarios. + DeliveryResultHandler() SimDeliveryResultHandler +} + +type ( + // FactoryMethod is a method signature implemented by concrete message factories for SimMsgFactoryX + // + // This factory method is responsible for creating a new `sdk.Msg` instance and determining the + // proposed signers who are expected to successfully sign the message for delivery. + // + // Parameters: + // - ctx: The context for the operation + // - testData: A pointer to a `ChainDataSource` which provides helper methods and simple access to accounts + // and balances within the chain. + // - reporter: An instance of `SimulationReporter` used to report the results of the simulation. + // If no valid message can be provided, the factory method should call `reporter.Skip("some comment")` + // with both `signer` and `msg` set to nil. + // + // Returns: + // - signer: A slice of `SimAccount` representing the proposed signers. + // - msg: An instance of `sdk.Msg` representing the message to be delivered. + FactoryMethod func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) + + // FactoryMethodWithFutureOps extended message factory method for the gov module or others that have to schedule operations for a future block. + FactoryMethodWithFutureOps[T sdk.Msg] func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter, fOpsReg FutureOpsRegistry) ([]SimAccount, T) + + // FactoryMethodWithDeliveryResultHandler extended factory method that can return a result handler, that is executed on the delivery tx error result. + // This is used in staking for example to validate negative execution results. + FactoryMethodWithDeliveryResultHandler[T sdk.Msg] func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg T, handler SimDeliveryResultHandler) +) + +var _ SimMsgFactoryX = &ResultHandlingSimMsgFactory[sdk.Msg]{} + +// ResultHandlingSimMsgFactory message factory with a delivery error result handler configured. +type ResultHandlingSimMsgFactory[T sdk.Msg] struct { + SimMsgFactoryFn[T] + resultHandler SimDeliveryResultHandler +} + +// NewSimMsgFactoryWithDeliveryResultHandler constructor +func NewSimMsgFactoryWithDeliveryResultHandler[T sdk.Msg](f FactoryMethodWithDeliveryResultHandler[T]) *ResultHandlingSimMsgFactory[T] { + // the result handler is always called after the factory. so we initialize it lazy for syntactic sugar and simplicity + // in the message factory function that is implemented by the users + var lazyResultHandler SimDeliveryResultHandler + r := &ResultHandlingSimMsgFactory[T]{ + resultHandler: func(err error) error { + return lazyResultHandler(err) + }, + } + r.SimMsgFactoryFn = func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg T) { + signer, msg, lazyResultHandler = f(ctx, testData, reporter) + if lazyResultHandler == nil { + lazyResultHandler = expectNoError + } + return + } + return r +} + +func (f ResultHandlingSimMsgFactory[T]) DeliveryResultHandler() SimDeliveryResultHandler { + return f.resultHandler +} + +var ( + _ SimMsgFactoryX = &LazyStateSimMsgFactory[sdk.Msg]{} + _ HasFutureOpsRegistry = &LazyStateSimMsgFactory[sdk.Msg]{} +) + +// LazyStateSimMsgFactory stateful message factory with weighted proposals and future operation +// registry initialized lazy before execution. +type LazyStateSimMsgFactory[T sdk.Msg] struct { + SimMsgFactoryFn[T] + fsOpsReg FutureOpsRegistry +} + +func NewSimMsgFactoryWithFutureOps[T sdk.Msg](f FactoryMethodWithFutureOps[T]) *LazyStateSimMsgFactory[T] { + r := &LazyStateSimMsgFactory[T]{} + r.SimMsgFactoryFn = func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg T) { + signer, msg = f(ctx, testData, reporter, r.fsOpsReg) + return + } + return r +} + +func (c *LazyStateSimMsgFactory[T]) SetFutureOpsRegistry(registry FutureOpsRegistry) { + c.fsOpsReg = registry +} + +// pass errors through and don't handle them +func expectNoError(err error) error { + return err +} + +var _ SimMsgFactoryX = SimMsgFactoryFn[sdk.Msg](nil) + +// SimMsgFactoryFn is the default factory for most cases. It does not create future operations but ensures successful message delivery. +type SimMsgFactoryFn[T sdk.Msg] func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg T) + +// MsgType returns an empty instance of type T, which implements `sdk.Msg`. +func (f SimMsgFactoryFn[T]) MsgType() sdk.Msg { + var x T + return x +} + +func (f SimMsgFactoryFn[T]) Create() FactoryMethod { + // adapter to return sdk.Msg instead of typed result to match FactoryMethod signature + return func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) ([]SimAccount, sdk.Msg) { + return f(ctx, testData, reporter) + } +} + +func (f SimMsgFactoryFn[T]) DeliveryResultHandler() SimDeliveryResultHandler { + return expectNoError +} + +func (f SimMsgFactoryFn[T]) Cast(msg sdk.Msg) T { + return msg.(T) +} + +type tuple struct { + signer []SimAccount + msg sdk.Msg +} + +// SafeRunFactoryMethod runs the factory method on a separate goroutine to abort early when the context is canceled via reporter skip +func SafeRunFactoryMethod( + ctx context.Context, + data *ChainDataSource, + reporter SimulationReporter, + f FactoryMethod, +) (signer []SimAccount, msg sdk.Msg) { + r := make(chan tuple) + go func() { + defer recoverPanicForSkipped(reporter, r) + signer, msg := f(ctx, data, reporter) + r <- tuple{signer: signer, msg: msg} + }() + select { + case t, ok := <-r: + if !ok { + return nil, nil + } + return t.signer, t.msg + case <-ctx.Done(): + reporter.Skip("context closed") + return nil, nil + } +} + +func recoverPanicForSkipped(reporter SimulationReporter, resultChan chan tuple) { + if r := recover(); r != nil { + if !reporter.IsSkipped() { + panic(r) + } + close(resultChan) + } +} diff --git a/simsx/msg_factory_test.go b/simsx/msg_factory_test.go new file mode 100644 index 000000000000..d5cadb222b69 --- /dev/null +++ b/simsx/msg_factory_test.go @@ -0,0 +1,97 @@ +package simsx + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestMsgFactories(t *testing.T) { + myMsg := testdata.NewTestMsg() + mySigners := []SimAccount{{}} + specs := map[string]struct { + src SimMsgFactoryX + expErrHandled bool + }{ + "default": { + src: SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) { + return mySigners, myMsg + }), + }, + "with delivery result handler": { + src: NewSimMsgFactoryWithDeliveryResultHandler[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg, handler SimDeliveryResultHandler) { + return mySigners, myMsg, func(err error) error { return nil } + }), + expErrHandled: true, + }, + "with future ops": { + src: NewSimMsgFactoryWithFutureOps[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter, fOpsReg FutureOpsRegistry) ([]SimAccount, *testdata.TestMsg) { + return mySigners, myMsg + }), + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + assert.Equal(t, (*testdata.TestMsg)(nil), spec.src.MsgType()) + + factoryMethod := spec.src.Create() + require.NotNil(t, factoryMethod) + gotSigners, gotMsg := factoryMethod(context.Background(), nil, nil) + assert.Equal(t, mySigners, gotSigners) + assert.Equal(t, gotMsg, myMsg) + + require.NotNil(t, spec.src.DeliveryResultHandler()) + gotErr := spec.src.DeliveryResultHandler()(errors.New("testing")) + assert.Equal(t, spec.expErrHandled, gotErr == nil) + }) + } +} + +func TestRunWithFailFast(t *testing.T) { + myTestMsg := testdata.NewTestMsg() + mySigners := []SimAccount{SimAccountFixture()} + specs := map[string]struct { + factory FactoryMethod + expSigners []SimAccount + expMsg sdk.Msg + expSkipped bool + }{ + "factory completes": { + factory: func(ctx context.Context, _ *ChainDataSource, reporter SimulationReporter) ([]SimAccount, sdk.Msg) { + return mySigners, myTestMsg + }, + expSigners: mySigners, + expMsg: myTestMsg, + }, + "factory skips": { + factory: func(ctx context.Context, _ *ChainDataSource, reporter SimulationReporter) ([]SimAccount, sdk.Msg) { + reporter.Skip("testing") + return nil, nil + }, + expSkipped: true, + }, + "factory skips and panics": { + factory: func(ctx context.Context, _ *ChainDataSource, reporter SimulationReporter) ([]SimAccount, sdk.Msg) { + reporter.Skip("testing") + panic("should be handled") + }, + expSkipped: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + ctx, done := context.WithCancel(context.Background()) + reporter := NewBasicSimulationReporter().WithScope(&testdata.TestMsg{}, SkipHookFn(func(...any) { done() })) + gotSigners, gotMsg := SafeRunFactoryMethod(ctx, nil, reporter, spec.factory) + assert.Equal(t, spec.expSigners, gotSigners) + assert.Equal(t, spec.expMsg, gotMsg) + assert.Equal(t, spec.expSkipped, reporter.IsSkipped()) + }) + } +} diff --git a/simsx/params.go b/simsx/params.go new file mode 100644 index 000000000000..7acd6edcf84f --- /dev/null +++ b/simsx/params.go @@ -0,0 +1,52 @@ +package simsx + +import ( + "math/rand" + + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +// WeightSource interface for retrieving weights based on a name and a default value. +type WeightSource interface { + Get(name string, defaultValue uint32) uint32 +} + +// WeightSourceFn function adapter that implements WeightSource. +// Example: +// +// weightSource := WeightSourceFn(func(name string, defaultValue uint32) uint32 { +// // implementation code... +// }) +type WeightSourceFn func(name string, defaultValue uint32) uint32 + +func (f WeightSourceFn) Get(name string, defaultValue uint32) uint32 { + return f(name, defaultValue) +} + +// ParamWeightSource is an adapter to the simtypes.AppParams object. This function returns a WeightSource +// implementation that retrieves weights +// based on a name and a default value. The implementation uses the provided AppParams +// to get or generate the weight value. If the weight value exists in the AppParams, +// it is decoded and returned. Otherwise, the provided ParamSimulator is used to generate +// a random value or default value. +// +// The WeightSource implementation is a WeightSourceFn function adapter that implements +// the WeightSource interface. It takes in a name string and a defaultValue uint32 as +// parameters and returns the weight value as a uint32. +// +// Example Usage: +// +// appParams := simtypes.AppParams{} +// // add parameters to appParams +// +// weightSource := ParamWeightSource(appParams) +// weightSource.Get("some_weight", 100) +func ParamWeightSource(p simtypes.AppParams) WeightSource { + return WeightSourceFn(func(name string, defaultValue uint32) uint32 { + var result uint32 + p.GetOrGenerate("op_weight_"+name, &result, nil, func(_ *rand.Rand) { + result = defaultValue + }) + return result + }) +} diff --git a/simsx/registry.go b/simsx/registry.go new file mode 100644 index 000000000000..6aee009f379d --- /dev/null +++ b/simsx/registry.go @@ -0,0 +1,268 @@ +package simsx + +import ( + "cmp" + "context" + "iter" + "maps" + "math/rand" + "slices" + "strings" + "time" + + "cosmossdk.io/core/address" + "cosmossdk.io/core/log" + + "github.com/cosmos/cosmos-sdk/client" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" +) + +type ( + // Registry is an abstract entry point to register message factories with weights + Registry interface { + Add(weight uint32, f SimMsgFactoryX) + } + // FutureOpsRegistry register message factories for future blocks + FutureOpsRegistry interface { + Add(blockTime time.Time, f SimMsgFactoryX) + } + + // AccountSourceX Account and Module account + AccountSourceX interface { + AccountSource + ModuleAccountSource + } +) + +// WeightedProposalMsgIter iterator for weighted gov proposal payload messages +type WeightedProposalMsgIter = iter.Seq2[uint32, FactoryMethod] + +var _ Registry = &WeightedOperationRegistryAdapter{} + +// common types for abstract registry without generics +type regCommon struct { + reporter SimulationReporter + ak AccountSourceX + bk BalanceSource + addressCodec address.Codec + txConfig client.TxConfig + logger log.Logger +} + +func (c regCommon) newChainDataSource(ctx context.Context, r *rand.Rand, accs ...simtypes.Account) *ChainDataSource { + return NewChainDataSource(ctx, r, c.ak, c.bk, c.addressCodec, accs...) +} + +type AbstractRegistry[T any] struct { + regCommon + legacyObjs []T +} + +// ToLegacyObjects returns the legacy properties of the SimsRegistryAdapter as a slice of type T. +func (l *AbstractRegistry[T]) ToLegacyObjects() []T { + return l.legacyObjs +} + +// WeightedOperationRegistryAdapter is an implementation of the Registry interface that provides adapters to use the new message factories +// with the legacy simulation system +type WeightedOperationRegistryAdapter struct { + AbstractRegistry[simtypes.WeightedOperation] +} + +// NewSimsMsgRegistryAdapter creates a new instance of SimsRegistryAdapter for WeightedOperation types. +func NewSimsMsgRegistryAdapter( + reporter SimulationReporter, + ak AccountSourceX, + bk BalanceSource, + txConfig client.TxConfig, + logger log.Logger, +) *WeightedOperationRegistryAdapter { + return &WeightedOperationRegistryAdapter{ + AbstractRegistry: AbstractRegistry[simtypes.WeightedOperation]{ + regCommon: regCommon{ + reporter: reporter, + ak: ak, + bk: bk, + txConfig: txConfig, + addressCodec: txConfig.SigningContext().AddressCodec(), + logger: logger, + }, + }, + } +} + +// Add adds a new weighted operation to the collection +func (l *WeightedOperationRegistryAdapter) Add(weight uint32, fx SimMsgFactoryX) { + if fx == nil { + panic("message factory must not be nil") + } + if weight == 0 { + return + } + obj := simulation.NewWeightedOperation(int(weight), legacyOperationAdapter(l.regCommon, fx)) + l.legacyObjs = append(l.legacyObjs, obj) +} + +type HasFutureOpsRegistry interface { + SetFutureOpsRegistry(FutureOpsRegistry) +} + +// msg factory to legacy Operation type +func legacyOperationAdapter(l regCommon, fx SimMsgFactoryX) simtypes.Operation { + return func( + r *rand.Rand, app AppEntrypoint, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + xCtx, done := context.WithCancel(ctx) + ctx = sdk.UnwrapSDKContext(xCtx) + testData := l.newChainDataSource(ctx, r, accs...) + reporter := l.reporter.WithScope(fx.MsgType(), SkipHookFn(func(args ...any) { done() })) + fOpsReg := NewFutureOpsRegistry(l) + if fx, ok := fx.(HasFutureOpsRegistry); ok { + fx.SetFutureOpsRegistry(fOpsReg) + } + from, msg := SafeRunFactoryMethod(ctx, testData, reporter, fx.Create()) + futOps := fOpsReg.legacyObjs + weightedOpsResult := DeliverSimsMsg(ctx, reporter, app, r, l.txConfig, l.ak, chainID, msg, fx.DeliveryResultHandler(), from...) + err := reporter.Close() + return weightedOpsResult, futOps, err + } +} + +func NewFutureOpsRegistry(l regCommon) *FutureOperationRegistryAdapter { + return &FutureOperationRegistryAdapter{regCommon: l} +} + +type FutureOperationRegistryAdapter AbstractRegistry[simtypes.FutureOperation] + +func (l *FutureOperationRegistryAdapter) Add(blockTime time.Time, fx SimMsgFactoryX) { + if fx == nil { + panic("message factory must not be nil") + } + if blockTime.IsZero() { + return + } + obj := simtypes.FutureOperation{ + BlockTime: blockTime, + Op: legacyOperationAdapter(l.regCommon, fx), + } + l.legacyObjs = append(l.legacyObjs, obj) +} + +var _ Registry = &UniqueTypeRegistry{} + +type UniqueTypeRegistry map[string]WeightedFactory + +func NewUniqueTypeRegistry() UniqueTypeRegistry { + return make(UniqueTypeRegistry) +} + +func (s UniqueTypeRegistry) Add(weight uint32, f SimMsgFactoryX) { + msgType := f.MsgType() + msgTypeURL := sdk.MsgTypeURL(msgType) + if _, exists := s[msgTypeURL]; exists { + panic("type is already registered: " + msgTypeURL) + } + s[msgTypeURL] = WeightedFactory{Weight: weight, Factory: f} +} + +// Iterator returns an iterator function for a Go for loop sorted by weight desc. +func (s UniqueTypeRegistry) Iterator() WeightedProposalMsgIter { + x := maps.Values(s) + sortedWeightedFactory := slices.SortedFunc(x, func(a, b WeightedFactory) int { + return a.Compare(b) + }) + + return func(yield func(uint32, FactoryMethod) bool) { + for _, v := range sortedWeightedFactory { + if !yield(v.Weight, v.Factory.Create()) { + return + } + } + } +} + +// WeightedFactory is a Weight Factory tuple +type WeightedFactory struct { + Weight uint32 + Factory SimMsgFactoryX +} + +// Compare compares the WeightedFactory f with another WeightedFactory b. +// The comparison is done by comparing the weight of f with the weight of b. +// If the weight of f is greater than the weight of b, it returns 1. +// If the weight of f is less than the weight of b, it returns -1. +// If the weights are equal, it compares the TypeURL of the factories using strings.Compare. +// Returns an integer indicating the comparison result. +func (f WeightedFactory) Compare(b WeightedFactory) int { + switch { + case f.Weight > b.Weight: + return 1 + case f.Weight < b.Weight: + return -1 + default: + return strings.Compare(sdk.MsgTypeURL(f.Factory.MsgType()), sdk.MsgTypeURL(b.Factory.MsgType())) + } +} + +// WeightedFactoryMethod is a data tuple used for registering legacy proposal operations +type WeightedFactoryMethod struct { + Weight uint32 + Factory FactoryMethod +} + +type WeightedFactoryMethods []WeightedFactoryMethod + +// NewWeightedFactoryMethods constructor +func NewWeightedFactoryMethods() WeightedFactoryMethods { + return make(WeightedFactoryMethods, 0) +} + +// Add adds a new WeightedFactoryMethod to the WeightedFactoryMethods slice. +// If weight is zero or f is nil, it returns without making any changes. +func (s *WeightedFactoryMethods) Add(weight uint32, f FactoryMethod) { + if weight == 0 { + return + } + if f == nil { + panic("message factory must not be nil") + } + *s = append(*s, WeightedFactoryMethod{Weight: weight, Factory: f}) +} + +// Iterator returns an iterator function for a Go for loop sorted by weight desc. +func (s WeightedFactoryMethods) Iterator() WeightedProposalMsgIter { + slices.SortFunc(s, func(e, e2 WeightedFactoryMethod) int { + return cmp.Compare(e.Weight, e2.Weight) + }) + return func(yield func(uint32, FactoryMethod) bool) { + for _, v := range s { + if !yield(v.Weight, v.Factory) { + return + } + } + } +} + +// legacy operation to Msg factory type +func legacyToMsgFactoryAdapter(fn simtypes.MsgSimulatorFnX) FactoryMethod { + return func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) { + msg, err := fn(ctx, testData.r, testData.AllAccounts(), testData.AddressCodec()) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + return []SimAccount{}, msg + } +} + +// AppendIterators takes multiple WeightedProposalMsgIter and returns a single iterator that sequentially yields items after each one. +func AppendIterators(iterators ...WeightedProposalMsgIter) WeightedProposalMsgIter { + return func(yield func(uint32, FactoryMethod) bool) { + for _, it := range iterators { + it(yield) + } + } +} diff --git a/simsx/registry_test.go b/simsx/registry_test.go new file mode 100644 index 000000000000..e8aba1239c7a --- /dev/null +++ b/simsx/registry_test.go @@ -0,0 +1,204 @@ +package simsx + +import ( + "context" + "errors" + "math/rand" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "cosmossdk.io/log" + + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +func TestSimsMsgRegistryAdapter(t *testing.T) { + senderAcc := SimAccountFixture() + accs := []simtypes.Account{senderAcc.Account} + ak := MockAccountSourceX{GetAccountFn: MemoryAccountSource(senderAcc).GetAccount} + myMsg := testdata.NewTestMsg(senderAcc.Address) + ctx := sdk.Context{}.WithContext(context.Background()) + futureTime := time.Now().Add(time.Second) + + specs := map[string]struct { + factory SimMsgFactoryX + expFactoryMsg sdk.Msg + expFactoryErr error + expDeliveryErr error + expFutureOpsCount int + }{ + "successful execution": { + factory: SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) { + return []SimAccount{senderAcc}, myMsg + }), + expFactoryMsg: myMsg, + }, + "skip execution": { + factory: SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) { + reporter.Skip("testing") + return nil, nil + }), + }, + "future ops registration": { + factory: NewSimMsgFactoryWithFutureOps[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter, fOpsReg FutureOpsRegistry) (signer []SimAccount, msg *testdata.TestMsg) { + fOpsReg.Add(futureTime, SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) { + return []SimAccount{senderAcc}, myMsg + })) + return []SimAccount{senderAcc}, myMsg + }), + expFactoryMsg: myMsg, + expFutureOpsCount: 1, + }, + "error in factory execution": { + factory: NewSimMsgFactoryWithFutureOps[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter, fOpsReg FutureOpsRegistry) (signer []SimAccount, msg *testdata.TestMsg) { + reporter.Fail(errors.New("testing")) + return nil, nil + }), + expFactoryErr: errors.New("testing"), + }, + "missing senders": { + factory: SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) { + return nil, myMsg + }), + expDeliveryErr: errors.New("no senders"), + }, + "error in delivery execution": { + factory: SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) { + return []SimAccount{senderAcc}, myMsg + }), + expDeliveryErr: errors.New("testing"), + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + r := NewBasicSimulationReporter() + reg := NewSimsMsgRegistryAdapter(r, ak, nil, txConfig(), log.NewNopLogger()) + // when + reg.Add(100, spec.factory) + // then + gotOps := reg.ToLegacyObjects() + require.Len(t, gotOps, 1) + assert.Equal(t, 100, gotOps[0].Weight()) + + // and when ops executed + var capturedTXs []sdk.Tx + captureTXApp := AppEntrypointFn(func(_txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) { + capturedTXs = append(capturedTXs, tx) + return sdk.GasInfo{}, &sdk.Result{}, spec.expDeliveryErr + }) + fn := gotOps[0].Op() + gotOpsResult, gotFOps, gotErr := fn(rand.New(rand.NewSource(1)), captureTXApp, ctx, accs, "testchain") + // then + if spec.expFactoryErr != nil { + require.Equal(t, spec.expFactoryErr, gotErr) + assert.Empty(t, gotFOps) + assert.Equal(t, gotOpsResult.OK, spec.expFactoryErr == nil) + assert.Empty(t, gotOpsResult.Comment) + require.Empty(t, capturedTXs) + } + if spec.expDeliveryErr != nil { + require.Equal(t, spec.expDeliveryErr, gotErr) + } + // and verify TX delivery + if spec.expFactoryMsg != nil { + require.Len(t, capturedTXs, 1) + require.Len(t, capturedTXs[0].GetMsgs(), 1) + assert.Equal(t, spec.expFactoryMsg, capturedTXs[0].GetMsgs()[0]) + } + assert.Len(t, gotFOps, spec.expFutureOpsCount) + }) + } +} + +func TestUniqueTypeRegistry(t *testing.T) { + exampleFactory := SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) { + return []SimAccount{}, nil + }) + + specs := map[string]struct { + src []WeightedFactory + exp []WeightedFactoryMethod + expErr bool + }{ + "unique": { + src: []WeightedFactory{{Weight: 1, Factory: exampleFactory}}, + exp: []WeightedFactoryMethod{{Weight: 1, Factory: exampleFactory.Create()}}, + }, + "duplicate": { + src: []WeightedFactory{{Weight: 1, Factory: exampleFactory}, {Weight: 2, Factory: exampleFactory}}, + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + reg := NewUniqueTypeRegistry() + if spec.expErr { + require.Panics(t, func() { + for _, v := range spec.src { + reg.Add(v.Weight, v.Factory) + } + }) + return + } + for _, v := range spec.src { + reg.Add(v.Weight, v.Factory) + } + // then + got := readAll(reg.Iterator()) + require.Len(t, got, len(spec.exp)) + }) + } +} + +func TestWeightedFactories(t *testing.T) { + r := NewWeightedFactoryMethods() + f1 := func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) { + panic("not implemented") + } + f2 := func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) { + panic("not implemented") + } + r.Add(1, f1) + r.Add(2, f2) + got := readAll(r.Iterator()) + require.Len(t, got, 2) + + assert.Equal(t, uint32(1), r[0].Weight) + assert.Equal(t, uint32(2), r[1].Weight) +} + +func TestAppendIterators(t *testing.T) { + r1 := NewWeightedFactoryMethods() + r1.Add(2, func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) { + panic("not implemented") + }) + r1.Add(2, func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) { + panic("not implemented") + }) + r1.Add(3, func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) { + panic("not implemented") + }) + r2 := NewUniqueTypeRegistry() + r2.Add(1, SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) { + panic("not implemented") + })) + // when + all := readAll(AppendIterators(r1.Iterator(), r2.Iterator())) + // then + require.Len(t, all, 4) + gotWeights := Collect(all, func(a WeightedFactoryMethod) uint32 { return a.Weight }) + assert.Equal(t, []uint32{2, 2, 3, 1}, gotWeights) +} + +func readAll(iterator WeightedProposalMsgIter) []WeightedFactoryMethod { + var ret []WeightedFactoryMethod + for w, f := range iterator { + ret = append(ret, WeightedFactoryMethod{Weight: w, Factory: f}) + } + return ret +} diff --git a/simsx/reporter.go b/simsx/reporter.go new file mode 100644 index 000000000000..556b739518a8 --- /dev/null +++ b/simsx/reporter.go @@ -0,0 +1,260 @@ +package simsx + +import ( + "errors" + "fmt" + "maps" + "slices" + "strings" + "sync" + "sync/atomic" + + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +// SimulationReporter is an interface for reporting the result of a simulation run. +type SimulationReporter interface { + WithScope(msg sdk.Msg, optionalSkipHook ...SkipHook) SimulationReporter + Skip(comment string) + Skipf(comment string, args ...any) + // IsSkipped returns true when skipped or completed + IsSkipped() bool + ToLegacyOperationMsg() simtypes.OperationMsg + // Fail complete with failure + Fail(err error, comments ...string) + // Success complete with success + Success(msg sdk.Msg, comments ...string) + // Close returns error captured on fail + Close() error + Comment() string +} + +var _ SimulationReporter = &BasicSimulationReporter{} + +type ReporterStatus uint8 + +const ( + undefined ReporterStatus = iota + skipped ReporterStatus = iota + completed ReporterStatus = iota +) + +func (s ReporterStatus) String() string { + switch s { + case skipped: + return "skipped" + case completed: + return "completed" + default: + return "undefined" + } +} + +// SkipHook is an interface that represents a callback hook used triggered on skip operations. +// It provides a single method `Skip` that accepts variadic arguments. This interface is implemented +// by Go stdlib testing.T and testing.B +type SkipHook interface { + Skip(args ...any) +} + +var _ SkipHook = SkipHookFn(nil) + +type SkipHookFn func(args ...any) + +func (s SkipHookFn) Skip(args ...any) { + s(args...) +} + +type BasicSimulationReporter struct { + skipCallbacks []SkipHook + completedCallback func(reporter *BasicSimulationReporter) + module string + msgTypeURL string + + status atomic.Uint32 + + cMX sync.RWMutex + comments []string + error error + + summary *ExecutionSummary +} + +// NewBasicSimulationReporter constructor that accepts an optional callback hook that is called on state transition to skipped status +// A typical implementation for this hook is testing.T or testing.B. +func NewBasicSimulationReporter(optionalSkipHook ...SkipHook) *BasicSimulationReporter { + r := &BasicSimulationReporter{ + skipCallbacks: optionalSkipHook, + summary: NewExecutionSummary(), + } + r.completedCallback = func(child *BasicSimulationReporter) { + r.summary.Add(child.module, child.msgTypeURL, ReporterStatus(child.status.Load()), child.Comment()) + } + return r +} + +// WithScope is a method of the BasicSimulationReporter type that creates a new instance of SimulationReporter +// with an additional scope specified by the input `msg`. The msg is used to set type, module and binary data as +// context for the legacy operation. +// The WithScope method acts as a constructor to initialize state and has to be called before using the instance +// in DeliverSimsMsg. +// +// The method accepts an optional `optionalSkipHook` parameter +// that can be used to add a callback hook that is triggered on skip operations additional to any parent skip hook. +// This method returns the newly created +// SimulationReporter instance. +func (x *BasicSimulationReporter) WithScope(msg sdk.Msg, optionalSkipHook ...SkipHook) SimulationReporter { + typeURL := sdk.MsgTypeURL(msg) + r := &BasicSimulationReporter{ + skipCallbacks: append(x.skipCallbacks, optionalSkipHook...), + completedCallback: x.completedCallback, + error: x.error, + msgTypeURL: typeURL, + module: sdk.GetModuleNameFromTypeURL(typeURL), + comments: slices.Clone(x.comments), + } + r.status.Store(x.status.Load()) + return r +} + +func (x *BasicSimulationReporter) Skip(comment string) { + x.toStatus(skipped, comment) +} + +func (x *BasicSimulationReporter) Skipf(comment string, args ...any) { + x.Skip(fmt.Sprintf(comment, args...)) +} + +func (x *BasicSimulationReporter) IsSkipped() bool { + return ReporterStatus(x.status.Load()) > undefined +} + +func (x *BasicSimulationReporter) ToLegacyOperationMsg() simtypes.OperationMsg { + switch ReporterStatus(x.status.Load()) { + case skipped: + return simtypes.NoOpMsg(x.module, x.msgTypeURL, x.Comment()) + case completed: + x.cMX.RLock() + err := x.error + x.cMX.RUnlock() + if err == nil { + return simtypes.NewOperationMsgBasic(x.module, x.msgTypeURL, x.Comment(), true) + } else { + return simtypes.NewOperationMsgBasic(x.module, x.msgTypeURL, x.Comment(), false) + } + default: + x.Fail(errors.New("operation aborted before msg was executed")) + return x.ToLegacyOperationMsg() + } +} + +func (x *BasicSimulationReporter) Fail(err error, comments ...string) { + if !x.toStatus(completed, comments...) { + return + } + x.cMX.Lock() + defer x.cMX.Unlock() + x.error = err +} + +func (x *BasicSimulationReporter) Success(msg sdk.Msg, comments ...string) { + if !x.toStatus(completed, comments...) { + return + } + if msg == nil { + return + } +} + +func (x *BasicSimulationReporter) Close() error { + x.completedCallback(x) + x.cMX.RLock() + defer x.cMX.RUnlock() + return x.error +} + +func (x *BasicSimulationReporter) toStatus(next ReporterStatus, comments ...string) bool { + oldStatus := ReporterStatus(x.status.Load()) + if oldStatus > next { + panic(fmt.Sprintf("can not switch from status %s to %s", oldStatus, next)) + } + if !x.status.CompareAndSwap(uint32(oldStatus), uint32(next)) { + return false + } + x.cMX.Lock() + newComments := append(x.comments, comments...) + x.comments = newComments + x.cMX.Unlock() + + if oldStatus != skipped && next == skipped { + prettyComments := strings.Join(newComments, ", ") + for _, hook := range x.skipCallbacks { + hook.Skip(prettyComments) + } + } + return true +} + +func (x *BasicSimulationReporter) Comment() string { + x.cMX.RLock() + defer x.cMX.RUnlock() + return strings.Join(x.comments, ", ") +} + +func (x *BasicSimulationReporter) Summary() *ExecutionSummary { + return x.summary +} + +type ExecutionSummary struct { + mx sync.RWMutex + counts map[string]int // module to count + skipReasons map[string]map[string]int // msg type to reason->count +} + +func NewExecutionSummary() *ExecutionSummary { + return &ExecutionSummary{counts: make(map[string]int), skipReasons: make(map[string]map[string]int)} +} + +func (s *ExecutionSummary) Add(module, url string, status ReporterStatus, comment string) { + s.mx.Lock() + defer s.mx.Unlock() + combinedKey := fmt.Sprintf("%s_%s", module, status.String()) + s.counts[combinedKey] += 1 + if status == completed { + return + } + r, ok := s.skipReasons[url] + if !ok { + r = make(map[string]int) + s.skipReasons[url] = r + } + r[comment] += 1 +} + +func (s *ExecutionSummary) String() string { + s.mx.RLock() + defer s.mx.RUnlock() + keys := slices.Sorted(maps.Keys(s.counts)) + var sb strings.Builder + for _, key := range keys { + sb.WriteString(fmt.Sprintf("%s: %d\n", key, s.counts[key])) + } + if len(s.skipReasons) != 0 { + sb.WriteString("\nSkip reasons:\n") + } + for m, c := range s.skipReasons { + values := maps.Values(c) + keys := maps.Keys(c) + sb.WriteString(fmt.Sprintf("%d\t%s: %q\n", sum(slices.Collect(values)), m, slices.Collect(keys))) + } + return sb.String() +} + +func sum(values []int) int { + var r int + for _, v := range values { + r += v + } + return r +} diff --git a/simsx/reporter_test.go b/simsx/reporter_test.go new file mode 100644 index 000000000000..2bc47fe902b0 --- /dev/null +++ b/simsx/reporter_test.go @@ -0,0 +1,219 @@ +package simsx + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/testutil/testdata" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +func TestSimulationReporterToLegacy(t *testing.T) { + myErr := errors.New("my-error") + myMsg := testdata.NewTestMsg([]byte{1}) + + specs := map[string]struct { + setup func() SimulationReporter + expOp simtypes.OperationMsg + expErr error + }{ + "init only": { + setup: func() SimulationReporter { return NewBasicSimulationReporter() }, + expOp: simtypes.NewOperationMsgBasic("", "", "", false), + expErr: errors.New("operation aborted before msg was executed"), + }, + "success result": { + setup: func() SimulationReporter { + r := NewBasicSimulationReporter().WithScope(myMsg) + r.Success(myMsg, "testing") + return r + }, + expOp: simtypes.NewOperationMsgBasic("TestMsg", "/testpb.TestMsg", "testing", true), + }, + "error result": { + setup: func() SimulationReporter { + r := NewBasicSimulationReporter().WithScope(myMsg) + r.Fail(myErr, "testing") + return r + }, + expOp: simtypes.NewOperationMsgBasic("TestMsg", "/testpb.TestMsg", "testing", false), + expErr: myErr, + }, + "last error wins": { + setup: func() SimulationReporter { + r := NewBasicSimulationReporter().WithScope(myMsg) + r.Fail(errors.New("other-err"), "testing1") + r.Fail(myErr, "testing2") + return r + }, + expOp: simtypes.NewOperationMsgBasic("TestMsg", "/testpb.TestMsg", "testing1, testing2", false), + expErr: myErr, + }, + "skipped ": { + setup: func() SimulationReporter { + r := NewBasicSimulationReporter().WithScope(myMsg) + r.Skip("testing") + return r + }, + expOp: simtypes.NoOpMsg("TestMsg", "/testpb.TestMsg", "testing"), + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + r := spec.setup() + assert.Equal(t, spec.expOp, r.ToLegacyOperationMsg()) + require.Equal(t, spec.expErr, r.Close()) + }) + } +} + +func TestSimulationReporterTransitions(t *testing.T) { + specs := map[string]struct { + setup func(r SimulationReporter) + expStatus ReporterStatus + expPanic bool + }{ + "undefined->skipped": { + setup: func(r SimulationReporter) { + r.Skip("testing") + }, + expStatus: skipped, + }, + "skipped->skipped": { + setup: func(r SimulationReporter) { + r.Skip("testing1") + r.Skip("testing2") + }, + expStatus: skipped, + }, + "skipped->completed": { + setup: func(r SimulationReporter) { + r.Skip("testing1") + r.Success(nil, "testing2") + }, + expStatus: completed, + }, + "completed->completed": { + setup: func(r SimulationReporter) { + r.Success(nil, "testing1") + r.Fail(nil, "testing2") + }, + expStatus: completed, + }, + "completed->completed2": { + setup: func(r SimulationReporter) { + r.Fail(nil, "testing1") + r.Success(nil, "testing2") + }, + expStatus: completed, + }, + "completed->skipped: rejected": { + setup: func(r SimulationReporter) { + r.Success(nil, "testing1") + r.Skip("testing2") + }, + expPanic: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + r := NewBasicSimulationReporter() + if !spec.expPanic { + spec.setup(r) + assert.Equal(t, uint32(spec.expStatus), r.status.Load()) + return + } + require.Panics(t, func() { + spec.setup(r) + }) + }) + } +} + +func TestSkipHook(t *testing.T) { + myHook := func() (SkipHookFn, *bool) { + var hookCalled bool + return func(args ...any) { + hookCalled = true + }, &hookCalled + } + fn, myHookCalled := myHook() + r := NewBasicSimulationReporter(fn) + r.Skip("testing") + require.True(t, *myHookCalled) + + // and with nested reporter + fn, myHookCalled = myHook() + r = NewBasicSimulationReporter(fn) + fn2, myOtherHookCalled := myHook() + r2 := r.WithScope(testdata.NewTestMsg([]byte{1}), fn2) + r2.Skipf("testing %d", 2) + assert.True(t, *myHookCalled) + assert.True(t, *myOtherHookCalled) +} + +func TestReporterSummary(t *testing.T) { + specs := map[string]struct { + do func(t *testing.T, r SimulationReporter) + expSummary map[string]int + expReasons map[string]map[string]int + }{ + "skipped": { + do: func(t *testing.T, r SimulationReporter) { //nolint:thelper // not a helper + r2 := r.WithScope(testdata.NewTestMsg([]byte{1})) + r2.Skip("testing") + require.NoError(t, r2.Close()) + }, + expSummary: map[string]int{"TestMsg_skipped": 1}, + expReasons: map[string]map[string]int{"/testpb.TestMsg": {"testing": 1}}, + }, + "success result": { + do: func(t *testing.T, r SimulationReporter) { //nolint:thelper // not a helper + msg := testdata.NewTestMsg([]byte{1}) + r2 := r.WithScope(msg) + r2.Success(msg) + require.NoError(t, r2.Close()) + }, + expSummary: map[string]int{"TestMsg_completed": 1}, + expReasons: map[string]map[string]int{}, + }, + "error result": { + do: func(t *testing.T, r SimulationReporter) { //nolint:thelper // not a helper + msg := testdata.NewTestMsg([]byte{1}) + r2 := r.WithScope(msg) + r2.Fail(errors.New("testing")) + require.Error(t, r2.Close()) + }, + expSummary: map[string]int{"TestMsg_completed": 1}, + expReasons: map[string]map[string]int{}, + }, + "multiple skipped": { + do: func(t *testing.T, r SimulationReporter) { //nolint:thelper // not a helper + r2 := r.WithScope(testdata.NewTestMsg([]byte{1})) + r2.Skip("testing1") + require.NoError(t, r2.Close()) + r3 := r.WithScope(testdata.NewTestMsg([]byte{2})) + r3.Skip("testing2") + require.NoError(t, r3.Close()) + }, + expSummary: map[string]int{"TestMsg_skipped": 2}, + expReasons: map[string]map[string]int{ + "/testpb.TestMsg": {"testing1": 1, "testing2": 1}, + }, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + r := NewBasicSimulationReporter() + // when + spec.do(t, r) + gotSummary := r.Summary() + // then + require.Equal(t, spec.expSummary, gotSummary.counts) + require.Equal(t, spec.expReasons, gotSummary.skipReasons) + }) + } +} diff --git a/simsx/runner.go b/simsx/runner.go new file mode 100644 index 000000000000..291f517a7448 --- /dev/null +++ b/simsx/runner.go @@ -0,0 +1,372 @@ +package simsx + +import ( + "encoding/json" + "fmt" + "io" + "os" + "path/filepath" + "testing" + + dbm "github.com/cosmos/cosmos-db" + "github.com/stretchr/testify/require" + + corestore "cosmossdk.io/core/store" + "cosmossdk.io/log" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/server" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" +) + +const SimAppChainID = "simulation-app" + +// this list of seeds was imported from the original simulation runner: https://github.com/cosmos/tools/blob/v1.0.0/cmd/runsim/main.go#L32 +var defaultSeeds = []int64{ + 1, 2, 4, 7, + 32, 123, 124, 582, 1893, 2989, + 3012, 4728, 37827, 981928, 87821, 891823782, + 989182, 89182391, 11, 22, 44, 77, 99, 2020, + 3232, 123123, 124124, 582582, 18931893, + 29892989, 30123012, 47284728, 7601778, 8090485, + 977367484, 491163361, 424254581, 673398983, +} + +// SimStateFactory is a factory type that provides a convenient way to create a simulation state for testing. +// It contains the following fields: +// - Codec: a codec used for serializing other objects +// - AppStateFn: a function that returns the app state JSON bytes and the genesis accounts +// - BlockedAddr: a map of blocked addresses +// - AccountSource: an interface for retrieving accounts +// - BalanceSource: an interface for retrieving balance-related information +type SimStateFactory struct { + Codec codec.Codec + AppStateFn simtypes.AppStateFn + BlockedAddr map[string]bool + AccountSource AccountSourceX + BalanceSource BalanceSource +} + +// SimulationApp abstract app that is used by sims +type SimulationApp interface { + runtime.AppSimI + SetNotSigverifyTx() + GetBaseApp() *baseapp.BaseApp + TxConfig() client.TxConfig + Close() error +} + +// Run is a helper function that runs a simulation test with the given parameters. +// It calls the RunWithSeeds function with the default seeds and parameters. +// +// This is the entrypoint to run simulation tests that used to run with the runsim binary. +func Run[T SimulationApp]( + t *testing.T, + appFactory func( + logger log.Logger, + db corestore.KVStoreWithBatch, + traceStore io.Writer, + loadLatest bool, + appOpts servertypes.AppOptions, + baseAppOptions ...func(*baseapp.BaseApp), + ) T, + setupStateFactory func(app T) SimStateFactory, + postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account), +) { + t.Helper() + RunWithSeeds(t, appFactory, setupStateFactory, defaultSeeds, nil, postRunActions...) +} + +// RunWithSeeds is a helper function that runs a simulation test with the given parameters. +// It iterates over the provided seeds and runs the simulation test for each seed in parallel. +// +// It sets up the environment, creates an instance of the simulation app, +// calls the simulation.SimulateFromSeed function to run the simulation, and performs post-run actions for each seed. +// The execution is deterministic and can be used for fuzz tests as well. +// +// The system under test is isolated for each run but unlike the old runsim command, there is no Process separation. +// This means, global caches may be reused for example. This implementation build upon the vanilla Go stdlib test framework. +func RunWithSeeds[T SimulationApp]( + t *testing.T, + appFactory func( + logger log.Logger, + db corestore.KVStoreWithBatch, + traceStore io.Writer, + loadLatest bool, + appOpts servertypes.AppOptions, + baseAppOptions ...func(*baseapp.BaseApp), + ) T, + setupStateFactory func(app T) SimStateFactory, + seeds []int64, + fuzzSeed []byte, + postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account), +) { + t.Helper() + cfg := cli.NewConfigFromFlags() + cfg.ChainID = SimAppChainID + for i := range seeds { + seed := seeds[i] + t.Run(fmt.Sprintf("seed: %d", seed), func(t *testing.T) { + t.Parallel() + RunWithSeed(t, cfg, appFactory, setupStateFactory, seed, fuzzSeed, postRunActions...) + }) + } +} + +// RunWithSeed is a helper function that runs a simulation test with the given parameters. +// It iterates over the provided seeds and runs the simulation test for each seed in parallel. +// +// It sets up the environment, creates an instance of the simulation app, +// calls the simulation.SimulateFromSeed function to run the simulation, and performs post-run actions for the seed. +// The execution is deterministic and can be used for fuzz tests as well. +func RunWithSeed[T SimulationApp]( + tb testing.TB, + cfg simtypes.Config, + appFactory func(logger log.Logger, db corestore.KVStoreWithBatch, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp)) T, + setupStateFactory func(app T) SimStateFactory, + seed int64, + fuzzSeed []byte, + postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account), +) { + tb.Helper() + // setup environment + tCfg := cfg.With(tb, seed, fuzzSeed) + testInstance := NewSimulationAppInstance(tb, tCfg, appFactory) + var runLogger log.Logger + if cli.FlagVerboseValue { + runLogger = log.NewTestLogger(tb) + } else { + runLogger = log.NewTestLoggerInfo(tb) + } + runLogger = runLogger.With("seed", tCfg.Seed) + + app := testInstance.App + stateFactory := setupStateFactory(app) + ops, reporter := prepareWeightedOps(app.SimulationManager(), stateFactory, tCfg, testInstance.App.TxConfig(), runLogger) + simParams, accs, err := simulation.SimulateFromSeedX(tb, runLogger, WriteToDebugLog(runLogger), app.GetBaseApp(), stateFactory.AppStateFn, simtypes.RandomAccounts, ops, stateFactory.BlockedAddr, tCfg, stateFactory.Codec, testInstance.ExecLogWriter) + require.NoError(tb, err) + err = simtestutil.CheckExportSimulation(app, tCfg, simParams) + require.NoError(tb, err) + if tCfg.Commit && tCfg.DBBackend == "goleveldb" { + simtestutil.PrintStats(testInstance.DB.(*dbm.GoLevelDB), tb.Log) + } + // not using tb.Log to always print the summary + fmt.Printf("+++ DONE (seed: %d): \n%s\n", seed, reporter.Summary().String()) + for _, step := range postRunActions { + step(tb, testInstance, accs) + } + require.NoError(tb, app.Close()) +} + +type ( + HasWeightedOperationsX interface { + WeightedOperationsX(weight WeightSource, reg Registry) + } + HasWeightedOperationsXWithProposals interface { + WeightedOperationsX(weights WeightSource, reg Registry, proposals WeightedProposalMsgIter, + legacyProposals []simtypes.WeightedProposalContent) //nolint: staticcheck // used for legacy proposal types + } + HasProposalMsgsX interface { + ProposalMsgsX(weights WeightSource, reg Registry) + } +) + +type ( + HasLegacyWeightedOperations interface { + // WeightedOperations simulation operations (i.e msgs) with their respective weight + WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation + } + // HasLegacyProposalMsgs defines the messages that can be used to simulate governance (v1) proposals + // Deprecated replaced by HasProposalMsgsX + HasLegacyProposalMsgs interface { + // ProposalMsgs msg fu nctions used to simulate governance proposals + ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg + } + + // HasLegacyProposalContents defines the contents that can be used to simulate legacy governance (v1beta1) proposals + // Deprecated replaced by HasProposalMsgsX + HasLegacyProposalContents interface { + // ProposalContents content functions used to simulate governance proposals + ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent //nolint:staticcheck // legacy v1beta1 governance + } +) + +// TestInstance is a generic type that represents an instance of a SimulationApp used for testing simulations. +// It contains the following fields: +// - App: The instance of the SimulationApp under test. +// - DB: The LevelDB database for the simulation app. +// - WorkDir: The temporary working directory for the simulation app. +// - Cfg: The configuration flags for the simulator. +// - AppLogger: The logger used for logging in the app during the simulation, with seed value attached. +// - ExecLogWriter: Captures block and operation data coming from the simulation +type TestInstance[T SimulationApp] struct { + App T + DB corestore.KVStoreWithBatch + WorkDir string + Cfg simtypes.Config + AppLogger log.Logger + ExecLogWriter simulation.LogWriter +} + +// included to avoid cyclic dependency in testutils/sims +func prepareWeightedOps( + sm *module.SimulationManager, + stateFact SimStateFactory, + config simtypes.Config, + txConfig client.TxConfig, + logger log.Logger, +) (simulation.WeightedOperations, *BasicSimulationReporter) { + cdc := stateFact.Codec + signingCtx := cdc.InterfaceRegistry().SigningContext() + simState := module.SimulationState{ + AppParams: make(simtypes.AppParams), + Cdc: cdc, + AddressCodec: signingCtx.AddressCodec(), + ValidatorCodec: signingCtx.ValidatorAddressCodec(), + TxConfig: txConfig, + BondDenom: sdk.DefaultBondDenom, + } + + if config.ParamsFile != "" { + bz, err := os.ReadFile(config.ParamsFile) + if err != nil { + panic(err) + } + + err = json.Unmarshal(bz, &simState.AppParams) + if err != nil { + panic(err) + } + } + + weights := ParamWeightSource(simState.AppParams) + reporter := NewBasicSimulationReporter() + + pReg := make(UniqueTypeRegistry) + wContent := make([]simtypes.WeightedProposalContent, 0) //nolint:staticcheck // required for legacy type + legacyPReg := NewWeightedFactoryMethods() + // add gov proposals types + for _, m := range sm.Modules { + switch xm := m.(type) { + case HasProposalMsgsX: + xm.ProposalMsgsX(weights, pReg) + case HasLegacyProposalMsgs: + for _, p := range xm.ProposalMsgs(simState) { + weight := weights.Get(p.AppParamsKey(), uint32(p.DefaultWeight())) + legacyPReg.Add(weight, legacyToMsgFactoryAdapter(p.MsgSimulatorFn())) + } + case HasLegacyProposalContents: + wContent = append(wContent, xm.ProposalContents(simState)...) + } + } + + oReg := NewSimsMsgRegistryAdapter(reporter, stateFact.AccountSource, stateFact.BalanceSource, txConfig, logger) + wOps := make([]simtypes.WeightedOperation, 0, len(sm.Modules)) + for _, m := range sm.Modules { + // add operations + switch xm := m.(type) { + case HasWeightedOperationsX: + xm.WeightedOperationsX(weights, oReg) + case HasWeightedOperationsXWithProposals: + xm.WeightedOperationsX(weights, oReg, AppendIterators(legacyPReg.Iterator(), pReg.Iterator()), wContent) + case HasLegacyWeightedOperations: + wOps = append(wOps, xm.WeightedOperations(simState)...) + } + } + return append(wOps, oReg.ToLegacyObjects()...), reporter +} + +// NewSimulationAppInstance initializes and returns a TestInstance of a SimulationApp. +// The function takes a testing.T instance, a simtypes.Config instance, and an appFactory function as parameters. +// It creates a temporary working directory and a LevelDB database for the simulation app. +// The function then initializes a logger based on the verbosity flag and sets the logger's seed to the test configuration's seed. +// The database is closed and cleaned up on test completion. +func NewSimulationAppInstance[T SimulationApp]( + tb testing.TB, + tCfg simtypes.Config, + appFactory func(logger log.Logger, db corestore.KVStoreWithBatch, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp)) T, +) TestInstance[T] { + tb.Helper() + workDir := tb.TempDir() + require.NoError(tb, os.Mkdir(filepath.Join(workDir, "data"), 0o755)) + dbDir := filepath.Join(workDir, "leveldb-app-sim") + var logger log.Logger + if cli.FlagVerboseValue { + logger = log.NewTestLogger(tb) + } else { + logger = log.NewTestLoggerError(tb) + } + logger = logger.With("seed", tCfg.Seed) + db, err := dbm.NewDB("Simulation", dbm.BackendType(tCfg.DBBackend), dbDir) + require.NoError(tb, err) + tb.Cleanup(func() { + _ = db.Close() // ensure db is closed + }) + appOptions := make(simtestutil.AppOptionsMap) + appOptions[flags.FlagHome] = workDir + appOptions[server.FlagInvCheckPeriod] = cli.FlagPeriodValue + opts := []func(*baseapp.BaseApp){baseapp.SetChainID(SimAppChainID)} + if tCfg.FauxMerkle { + opts = append(opts, FauxMerkleModeOpt) + } + app := appFactory(logger, db, nil, true, appOptions, opts...) + if !cli.FlagSigverifyTxValue { + app.SetNotSigverifyTx() + } + return TestInstance[T]{ + App: app, + DB: db, + WorkDir: workDir, + Cfg: tCfg, + AppLogger: logger, + ExecLogWriter: &simulation.StandardLogWriter{Seed: tCfg.Seed}, + } +} + +var _ io.Writer = writerFn(nil) + +type writerFn func(p []byte) (n int, err error) + +func (w writerFn) Write(p []byte) (n int, err error) { + return w(p) +} + +// WriteToDebugLog is an adapter to io.Writer interface +func WriteToDebugLog(logger log.Logger) io.Writer { + return writerFn(func(p []byte) (n int, err error) { + logger.Debug(string(p)) + return len(p), nil + }) +} + +// AppOptionsFn is an adapter to the single method AppOptions interface +type AppOptionsFn func(string) any + +func (f AppOptionsFn) Get(k string) any { + return f(k) +} + +func (f AppOptionsFn) GetString(k string) string { + str, ok := f(k).(string) + if !ok { + return "" + } + + return str +} + +// FauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of +// an IAVLStore for faster simulation speed. +func FauxMerkleModeOpt(bapp *baseapp.BaseApp) { + bapp.SetFauxMerkleMode() +} diff --git a/simsx/slices.go b/simsx/slices.go new file mode 100644 index 000000000000..3466cd6f971c --- /dev/null +++ b/simsx/slices.go @@ -0,0 +1,38 @@ +package simsx + +// Collect applies the function f to each element in the source slice, +// returning a new slice containing the results. +// +// The source slice can contain elements of any type T, and the function f +// should take an element of type T as input and return a value of any type E. +// +// Example usage: +// +// source := []int{1, 2, 3, 4, 5} +// double := Collect(source, func(x int) int { +// return x * 2 +// }) +// // double is now []int{2, 4, 6, 8, 10} +func Collect[T, E any](source []T, f func(a T) E) []E { + r := make([]E, len(source)) + for i, v := range source { + r[i] = f(v) + } + return r +} + +// First returns the first element in the slice that matches the condition +func First[T any](source []T, f func(a T) bool) *T { + for i := 0; i < len(source); i++ { + if f(source[i]) { + return &source[i] + } + } + return nil +} + +// OneOf returns a random element from the given slice using the provided random number generator. +// Panics for empty or nil slice +func OneOf[T any](r interface{ Intn(n int) int }, s []T) T { + return s[r.Intn(len(s))] +} diff --git a/simsx/slices_test.go b/simsx/slices_test.go new file mode 100644 index 000000000000..40decc173bd2 --- /dev/null +++ b/simsx/slices_test.go @@ -0,0 +1,40 @@ +package simsx + +import ( + "strconv" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCollect(t *testing.T) { + src := []int{1, 2, 3} + got := Collect(src, func(a int) int { return a * 2 }) + assert.Equal(t, []int{2, 4, 6}, got) + gotStrings := Collect(src, strconv.Itoa) + assert.Equal(t, []string{"1", "2", "3"}, gotStrings) +} + +func TestFirst(t *testing.T) { + src := []string{"a", "b"} + assert.Equal(t, &src[1], First(src, func(a string) bool { return a == "b" })) + assert.Nil(t, First(src, func(a string) bool { return false })) +} + +func TestOneOf(t *testing.T) { + src := []string{"a", "b"} + got := OneOf(randMock{next: 1}, src) + assert.Equal(t, "b", got) + // test with other type + src2 := []int{1, 2, 3} + got2 := OneOf(randMock{next: 2}, src2) + assert.Equal(t, 3, got2) +} + +type randMock struct { + next int +} + +func (x randMock) Intn(n int) int { + return x.next +} diff --git a/store/cachekv/search_test.go b/store/cachekv/search_test.go index 41321c076eae..aedc0669030a 100644 --- a/store/cachekv/search_test.go +++ b/store/cachekv/search_test.go @@ -60,7 +60,6 @@ func TestFindStartIndex(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { body := tt.sortedL got := findStartIndex(body, tt.query) @@ -129,7 +128,6 @@ func TestFindEndIndex(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { body := tt.sortedL got := findEndIndex(body, tt.query) diff --git a/store/cachekv/store.go b/store/cachekv/store.go index bce28e4b2d3f..3509cef6aee3 100644 --- a/store/cachekv/store.go +++ b/store/cachekv/store.go @@ -300,7 +300,7 @@ func (store *Store) dirtyItems(start, end []byte) { } n := len(store.unsortedCache) - unsorted := make([]*kv.Pair, 0) + unsorted := make([]*kv.Pair, 0) //nolint:staticcheck // We are in store v1. // If the unsortedCache is too big, its costs too much to determine // what's in the subset we are concerned about. // If you are interleaving iterator calls with writes, this can easily become an @@ -312,7 +312,7 @@ func (store *Store) dirtyItems(start, end []byte) { // dbm.IsKeyInDomain is nil safe and returns true iff key is greater than start if dbm.IsKeyInDomain(conv.UnsafeStrToBytes(key), start, end) { cacheValue := store.cache[key] - unsorted = append(unsorted, &kv.Pair{Key: []byte(key), Value: cacheValue.value}) + unsorted = append(unsorted, &kv.Pair{Key: []byte(key), Value: cacheValue.value}) //nolint:staticcheck // We are in store v1. } } store.clearUnsortedCacheSubset(unsorted, stateUnsorted) @@ -355,18 +355,18 @@ func (store *Store) dirtyItems(start, end []byte) { } } - kvL := make([]*kv.Pair, 0, 1+endIndex-startIndex) + kvL := make([]*kv.Pair, 0, 1+endIndex-startIndex) //nolint:staticcheck // We are in store v1. for i := startIndex; i <= endIndex; i++ { key := strL[i] cacheValue := store.cache[key] - kvL = append(kvL, &kv.Pair{Key: []byte(key), Value: cacheValue.value}) + kvL = append(kvL, &kv.Pair{Key: []byte(key), Value: cacheValue.value}) //nolint:staticcheck // We are in store v1. } // kvL was already sorted so pass it in as is. store.clearUnsortedCacheSubset(kvL, stateAlreadySorted) } -func (store *Store) clearUnsortedCacheSubset(unsorted []*kv.Pair, sortState sortState) { +func (store *Store) clearUnsortedCacheSubset(unsorted []*kv.Pair, sortState sortState) { //nolint:staticcheck // We are in store v1. n := len(store.unsortedCache) if len(unsorted) == n { // This pattern allows the Go compiler to emit the map clearing idiom for the entire map. for key := range store.unsortedCache { diff --git a/store/cachekv/store_test.go b/store/cachekv/store_test.go index f48f919c3504..2885e7125476 100644 --- a/store/cachekv/store_test.go +++ b/store/cachekv/store_test.go @@ -475,6 +475,10 @@ func doOp(t *testing.T, st types.CacheKVStore, truth corestore.KVStoreWithBatch, err := truth.Set(keyFmt(k), valFmt(k)) require.NoError(t, err) case opSetRange: + if len(args) < 2 { + panic("expected 2 args") + } + start := args[0] end := args[1] setRange(t, st, truth, start, end) @@ -484,6 +488,10 @@ func doOp(t *testing.T, st types.CacheKVStore, truth corestore.KVStoreWithBatch, err := truth.Delete(keyFmt(k)) require.NoError(t, err) case opDelRange: + if len(args) < 2 { + panic("expected 2 args") + } + start := args[0] end := args[1] deleteRange(t, st, truth, start, end) diff --git a/store/go.mod b/store/go.mod index 108f9bb708f6..db8d6c7ca5ef 100644 --- a/store/go.mod +++ b/store/go.mod @@ -2,8 +2,6 @@ module cosmossdk.io/store go 1.23 -toolchain go1.23.0 - require ( cosmossdk.io/core v1.0.0-alpha.2 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 @@ -23,7 +21,6 @@ require ( github.com/stretchr/testify v1.9.0 github.com/tidwall/btree v1.7.0 go.uber.org/mock v0.4.0 - golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 google.golang.org/grpc v1.66.2 google.golang.org/protobuf v1.34.2 gotest.tools/v3 v3.5.1 @@ -50,6 +47,7 @@ require ( github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/zerolog v1.33.0 // indirect golang.org/x/crypto v0.27.0 // indirect + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect golang.org/x/net v0.29.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/text v0.18.0 // indirect @@ -57,6 +55,4 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace cosmossdk.io/core => ../core - replace cosmossdk.io/core/testing => ../core/testing diff --git a/store/go.sum b/store/go.sum index 4fb7abb073ff..f2ef656d5b67 100644 --- a/store/go.sum +++ b/store/go.sum @@ -1,3 +1,5 @@ +cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= +cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= diff --git a/store/iavl/store.go b/store/iavl/store.go index 789e7c5d5eb1..ae6b0b56ff70 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -361,8 +361,8 @@ func (st *Store) Query(req *types.RequestQuery) (res *types.ResponseQuery, err e res.ProofOps = getProofFromTree(mtree, req.Data, res.Value != nil) case "/subspace": - pairs := kv.Pairs{ - Pairs: make([]kv.Pair, 0), + pairs := kv.Pairs{ //nolint:staticcheck // We are in store v1. + Pairs: make([]kv.Pair, 0), //nolint:staticcheck // We are in store v1. } subspace := req.Data @@ -370,7 +370,7 @@ func (st *Store) Query(req *types.RequestQuery) (res *types.ResponseQuery, err e iterator := types.KVStorePrefixIterator(st, subspace) for ; iterator.Valid(); iterator.Next() { - pairs.Pairs = append(pairs.Pairs, kv.Pair{Key: iterator.Key(), Value: iterator.Value()}) + pairs.Pairs = append(pairs.Pairs, kv.Pair{Key: iterator.Key(), Value: iterator.Value()}) //nolint:staticcheck // We are in store v1. } if err := iterator.Close(); err != nil { panic(fmt.Errorf("failed to close iterator: %w", err)) diff --git a/store/iavl/store_test.go b/store/iavl/store_test.go index ab6abbde05a6..d0339c59a107 100644 --- a/store/iavl/store_test.go +++ b/store/iavl/store_test.go @@ -478,15 +478,15 @@ func TestIAVLStoreQuery(t *testing.T) { v3 := []byte("val3") ksub := []byte("key") - KVs0 := kv.Pairs{} - KVs1 := kv.Pairs{ - Pairs: []kv.Pair{ + KVs0 := kv.Pairs{} //nolint:staticcheck // We are in store v1. + KVs1 := kv.Pairs{ //nolint:staticcheck // We are in store v1. + Pairs: []kv.Pair{ //nolint:staticcheck // We are in store v1. {Key: k1, Value: v1}, {Key: k2, Value: v2}, }, } - KVs2 := kv.Pairs{ - Pairs: []kv.Pair{ + KVs2 := kv.Pairs{ //nolint:staticcheck // We are in store v1. + Pairs: []kv.Pair{ //nolint:staticcheck // We are in store v1. {Key: k1, Value: v3}, {Key: k2, Value: v2}, }, @@ -639,8 +639,6 @@ func TestSetInitialVersion(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { db := coretesting.NewMemDB() store := tc.storeFn(db) diff --git a/store/internal/maps/maps.go b/store/internal/maps/maps.go index 6db2be666cae..f2c6117c737b 100644 --- a/store/internal/maps/maps.go +++ b/store/internal/maps/maps.go @@ -14,13 +14,13 @@ import ( // merkleMap defines a merkle-ized tree from a map. Leave values are treated as // hash(key) | hash(value). Leaves are sorted before Merkle hashing. type merkleMap struct { - kvs kv.Pairs + kvs kv.Pairs //nolint:staticcheck // We are in store v1. sorted bool } func newMerkleMap() *merkleMap { return &merkleMap{ - kvs: kv.Pairs{}, + kvs: kv.Pairs{}, //nolint:staticcheck // We are in store v1. sorted: false, } } @@ -38,7 +38,7 @@ func (sm *merkleMap) set(key string, value []byte) { // and make a determination to fetch or not. vhash := sha256.Sum256(value) - sm.kvs.Pairs = append(sm.kvs.Pairs, kv.Pair{ + sm.kvs.Pairs = append(sm.kvs.Pairs, kv.Pair{ //nolint:staticcheck // We are in store v1. Key: byteKey, Value: vhash[:], }) @@ -61,7 +61,7 @@ func (sm *merkleMap) sort() { // hashKVPairs hashes a kvPair and creates a merkle tree where the leaves are // byte slices. -func hashKVPairs(kvs kv.Pairs) []byte { +func hashKVPairs(kvs kv.Pairs) []byte { //nolint:staticcheck // We are in store v1. kvsH := make([][]byte, len(kvs.Pairs)) for i, kvp := range kvs.Pairs { kvsH[i] = KVPair(kvp).Bytes() @@ -76,13 +76,13 @@ func hashKVPairs(kvs kv.Pairs) []byte { // Leaves are `hash(key) | hash(value)`. // Leaves are sorted before Merkle hashing. type simpleMap struct { - Kvs kv.Pairs + Kvs kv.Pairs //nolint:staticcheck // We are in store v1. sorted bool } func newSimpleMap() *simpleMap { return &simpleMap{ - Kvs: kv.Pairs{}, + Kvs: kv.Pairs{}, //nolint:staticcheck // We are in store v1. sorted: false, } } @@ -99,7 +99,7 @@ func (sm *simpleMap) Set(key string, value []byte) { // and make a determination to fetch or not. vhash := sha256.Sum256(value) - sm.Kvs.Pairs = append(sm.Kvs.Pairs, kv.Pair{ + sm.Kvs.Pairs = append(sm.Kvs.Pairs, kv.Pair{ //nolint:staticcheck // We are in store v1. Key: byteKey, Value: vhash[:], }) @@ -122,10 +122,10 @@ func (sm *simpleMap) Sort() { // KVPairs returns a copy of sorted KVPairs. // NOTE these contain the hashed key and value. -func (sm *simpleMap) KVPairs() kv.Pairs { +func (sm *simpleMap) KVPairs() kv.Pairs { //nolint:staticcheck // We are in store v1. sm.Sort() - kvs := kv.Pairs{ - Pairs: make([]kv.Pair, len(sm.Kvs.Pairs)), + kvs := kv.Pairs{ //nolint:staticcheck // We are in store v1. + Pairs: make([]kv.Pair, len(sm.Kvs.Pairs)), //nolint:staticcheck // We are in store v1. } copy(kvs.Pairs, sm.Kvs.Pairs) @@ -137,12 +137,12 @@ func (sm *simpleMap) KVPairs() kv.Pairs { // KVPair is a local extension to KVPair that can be hashed. // Key and value are length prefixed and concatenated, // then hashed. -type KVPair kv.Pair +type KVPair kv.Pair //nolint:staticcheck // We are in store v1. // NewKVPair takes in a key and value and creates a kv.Pair // wrapped in the local extension KVPair func NewKVPair(key, value []byte) KVPair { - return KVPair(kv.Pair{ + return KVPair(kv.Pair{ //nolint:staticcheck // We are in store v1. Key: key, Value: value, }) diff --git a/store/internal/proofs/helpers.go b/store/internal/proofs/helpers.go index a87a692212ce..b82c96fe9c49 100644 --- a/store/internal/proofs/helpers.go +++ b/store/internal/proofs/helpers.go @@ -1,10 +1,10 @@ package proofs import ( - "sort" + "maps" + "slices" cmtprotocrypto "github.com/cometbft/cometbft/api/cometbft/crypto/v1" - "golang.org/x/exp/maps" "cosmossdk.io/math/unsafe" sdkmaps "cosmossdk.io/store/internal/maps" @@ -47,9 +47,7 @@ const ( ) func SortedKeys(data map[string][]byte) []string { - keys := maps.Keys(data) - sort.Strings(keys) - return keys + return slices.Sorted(maps.Keys(data)) } func CalcRoot(data map[string][]byte) []byte { diff --git a/store/listenkv/store_test.go b/store/listenkv/store_test.go index 3425097db100..7b1b17fd6755 100644 --- a/store/listenkv/store_test.go +++ b/store/listenkv/store_test.go @@ -19,7 +19,7 @@ func bz(s string) []byte { return []byte(s) } func keyFmt(i int) []byte { return bz(fmt.Sprintf("key%0.8d", i)) } func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } -var kvPairs = []kv.Pair{ +var kvPairs = []kv.Pair{ //nolint:staticcheck // We are in store v1. {Key: keyFmt(1), Value: valFmt(1)}, {Key: keyFmt(2), Value: valFmt(2)}, {Key: keyFmt(3), Value: valFmt(3)}, diff --git a/store/pruning/manager_test.go b/store/pruning/manager_test.go index 19cbe5deb42f..0f62a36c5b07 100644 --- a/store/pruning/manager_test.go +++ b/store/pruning/manager_test.go @@ -75,7 +75,7 @@ func TestStrategies(t *testing.T) { } for name, tc := range testcases { - tc := tc // Local copy to avoid shadowing. + // Local copy to avoid shadowing. t.Run(name, func(t *testing.T) { t.Parallel() diff --git a/store/rootmulti/snapshot_test.go b/store/rootmulti/snapshot_test.go index 35a2a0c569f7..fc00f5be25d9 100644 --- a/store/rootmulti/snapshot_test.go +++ b/store/rootmulti/snapshot_test.go @@ -142,7 +142,6 @@ func TestMultistoreSnapshot_Checksum(t *testing.T) { }}, } for _, tc := range testcases { - tc := tc t.Run(fmt.Sprintf("Format %v", tc.format), func(t *testing.T) { ch := make(chan io.ReadCloser) go func() { @@ -177,7 +176,6 @@ func TestMultistoreSnapshot_Errors(t *testing.T) { "unknown height": {9, nil}, } for name, tc := range testcases { - tc := tc t.Run(name, func(t *testing.T) { err := store.Snapshot(tc.height, nil) require.Error(t, err) diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index cd2029a5f707..31d24ed1205c 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -524,8 +524,6 @@ func TestMultiStore_Pruning(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { db := coretesting.NewMemDB() ms := newMultiStoreWithMounts(db, tc.po) diff --git a/store/tracekv/store_test.go b/store/tracekv/store_test.go index ae4136cce87f..5ad933cb67b0 100644 --- a/store/tracekv/store_test.go +++ b/store/tracekv/store_test.go @@ -21,7 +21,7 @@ func bz(s string) []byte { return []byte(s) } func keyFmt(i int) []byte { return bz(fmt.Sprintf("key%0.8d", i)) } func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } -var kvPairs = []kv.Pair{ +var kvPairs = []kv.Pair{ //nolint:staticcheck // We are in store v1. {Key: keyFmt(1), Value: valFmt(1)}, {Key: keyFmt(2), Value: valFmt(2)}, {Key: keyFmt(3), Value: valFmt(3)}, diff --git a/store/types/gas_test.go b/store/types/gas_test.go index f4b5a6abe5ba..a4f63ab6d999 100644 --- a/store/types/gas_test.go +++ b/store/types/gas_test.go @@ -47,7 +47,6 @@ func TestGasMeter(t *testing.T) { used := uint64(0) for unum, usage := range tc.usage { - usage := usage used += usage require.NotPanics(t, func() { meter.ConsumeGas(usage, "") }, "Not exceeded limit but panicked. tc #%d, usage #%d", tcnum, unum) require.Equal(t, used, meter.GasConsumed(), "Gas consumption not match. tc #%d, usage #%d", tcnum, unum) diff --git a/store/types/iterator_test.go b/store/types/iterator_test.go index e520acd85792..f8a1af65b83a 100644 --- a/store/types/iterator_test.go +++ b/store/types/iterator_test.go @@ -84,7 +84,6 @@ func TestPaginatedIterator(t *testing.T) { reverse: true, }, } { - tc := tc t.Run(tc.desc, func(t *testing.T) { var iter types.Iterator if tc.reverse { diff --git a/store/types/store_test.go b/store/types/store_test.go index b6304d131bc2..4a77c7babea8 100644 --- a/store/types/store_test.go +++ b/store/types/store_test.go @@ -53,7 +53,6 @@ func TestStoreUpgrades(t *testing.T) { } for name, tc := range cases { - tc := tc t.Run(name, func(t *testing.T) { for _, r := range tc.expectAdd { assert.Equal(t, tc.upgrades.IsAdded(r.key), true) diff --git a/store/v2/commitment/metadata.go b/store/v2/commitment/metadata.go index 7462252e962b..d7aea487c706 100644 --- a/store/v2/commitment/metadata.go +++ b/store/v2/commitment/metadata.go @@ -113,7 +113,10 @@ func (m *MetadataStore) flushCommitInfo(version uint64, cInfo *proof.CommitInfo) func (m *MetadataStore) flushRemovedStoreKeys(version uint64, storeKeys []string) (err error) { batch := m.kv.NewBatch() defer func() { - err = batch.Close() + cErr := batch.Close() + if err == nil { + err = cErr + } }() for _, storeKey := range storeKeys { diff --git a/store/v2/go.mod b/store/v2/go.mod index 6cc9d1d067a3..f52f42476d4c 100644 --- a/store/v2/go.mod +++ b/store/v2/go.mod @@ -49,7 +49,7 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/store/v2/go.sum b/store/v2/go.sum index ce946b663c0c..cc3df7efc56a 100644 --- a/store/v2/go.sum +++ b/store/v2/go.sum @@ -176,8 +176,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/store/v2/root/factory.go b/store/v2/root/factory.go index 4dfa01966314..e6f86917ab0d 100644 --- a/store/v2/root/factory.go +++ b/store/v2/root/factory.go @@ -109,6 +109,8 @@ func CreateRootStore(opts *FactoryOptions) (store.RootStore, error) { return nil, err } ssDb, err = rocksdb.New(dir) + default: + return nil, fmt.Errorf("unknown storage type: %s", opts.Options.SSType) } if err != nil { return nil, err @@ -168,12 +170,12 @@ func CreateRootStore(opts *FactoryOptions) (store.RootStore, error) { } oldTrees[string(key)] = tree } + sc, err = commitment.NewCommitStore(trees, oldTrees, opts.SCRawDB, opts.Logger) if err != nil { return nil, err } pm := pruning.NewManager(sc, ss, storeOpts.SCPruningOption, storeOpts.SSPruningOption) - return New(opts.Logger, ss, sc, pm, nil, nil) } diff --git a/store/v2/root/store_test.go b/store/v2/root/store_test.go index eddaea730652..e8cf34e014e0 100644 --- a/store/v2/root/store_test.go +++ b/store/v2/root/store_test.go @@ -456,7 +456,6 @@ func (s *RootStoreTestSuite) TestPrune() { } for _, tc := range testCases { - tc := tc s.newStoreWithPruneConfig(&tc.po) diff --git a/store/v2/storage/pebbledb/db.go b/store/v2/storage/pebbledb/db.go index ebcd242af243..8c7b822600d1 100644 --- a/store/v2/storage/pebbledb/db.go +++ b/store/v2/storage/pebbledb/db.go @@ -203,7 +203,7 @@ func (db *Database) Get(storeKey []byte, targetVersion uint64, key []byte) ([]by // database in order to delete them. // // See: https://github.com/cockroachdb/cockroach/blob/33623e3ee420174a4fd3226d1284b03f0e3caaac/pkg/storage/mvcc.go#L3182 -func (db *Database) Prune(version uint64) error { +func (db *Database) Prune(version uint64) (err error) { itr, err := db.storage.NewIter(&pebble.IterOptions{LowerBound: []byte("s/k:")}) if err != nil { return err @@ -211,7 +211,12 @@ func (db *Database) Prune(version uint64) error { defer itr.Close() batch := db.storage.NewBatch() - defer batch.Close() + defer func() { + cErr := batch.Close() + if err == nil { + err = cErr + } + }() var ( batchCounter int @@ -331,9 +336,14 @@ func (db *Database) ReverseIterator(storeKey []byte, version uint64, start, end return newPebbleDBIterator(itr, storePrefix(storeKey), start, end, version, db.earliestVersion, true), nil } -func (db *Database) PruneStoreKeys(storeKeys []string, version uint64) error { +func (db *Database) PruneStoreKeys(storeKeys []string, version uint64) (err error) { batch := db.storage.NewBatch() - defer batch.Close() + defer func() { + cErr := batch.Close() + if err == nil { + err = cErr + } + }() for _, storeKey := range storeKeys { if err := batch.Set([]byte(fmt.Sprintf("%s%s", encoding.BuildPrefixWithVersion(removedStoreKeyPrefix, version), storeKey)), []byte{}, nil); err != nil { @@ -428,9 +438,14 @@ func getMVCCSlice(db *pebble.DB, storeKey, key []byte, version uint64) ([]byte, return slices.Clone(value), err } -func (db *Database) deleteRemovedStoreKeys(version uint64) error { +func (db *Database) deleteRemovedStoreKeys(version uint64) (err error) { batch := db.storage.NewBatch() - defer batch.Close() + defer func() { + cErr := batch.Close() + if err == nil { + err = cErr + } + }() end := encoding.BuildPrefixWithVersion(removedStoreKeyPrefix, version+1) storeKeyIter, err := db.storage.NewIter(&pebble.IterOptions{LowerBound: []byte(removedStoreKeyPrefix), UpperBound: end}) diff --git a/tests/e2e/accounts/base_account_test.go b/tests/e2e/accounts/base_account_test.go index fcd43e6940eb..80c181e0bc6e 100644 --- a/tests/e2e/accounts/base_account_test.go +++ b/tests/e2e/accounts/base_account_test.go @@ -6,10 +6,14 @@ import ( "math/rand" "testing" + gogoany "github.com/cosmos/gogoproto/types/any" + "cosmossdk.io/simapp" baseaccountv1 "cosmossdk.io/x/accounts/defaults/base/v1" "cosmossdk.io/x/bank/testutil" banktypes "cosmossdk.io/x/bank/types" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" @@ -22,7 +26,7 @@ func TestBaseAccount(t *testing.T) { ctx := sdk.NewContext(app.CommitMultiStore(), false, app.Logger()) _, baseAccountAddr, err := ak.Init(ctx, "base", accCreator, &baseaccountv1.MsgInit{ - PubKey: privKey.PubKey().Bytes(), + PubKey: toAnyPb(t, privKey.PubKey()), }, nil) require.NoError(t, err) @@ -80,3 +84,13 @@ func bechify(t *testing.T, app *simapp.SimApp, addr []byte) string { func fundAccount(t *testing.T, app *simapp.SimApp, ctx sdk.Context, addr sdk.AccAddress, amt string) { require.NoError(t, testutil.FundAccount(ctx, app.BankKeeper, addr, coins(t, amt))) } + +func toAnyPb(t *testing.T, pm gogoproto.Message) *codectypes.Any { + t.Helper() + if gogoproto.MessageName(pm) == gogoproto.MessageName(&gogoany.Any{}) { + t.Fatal("no") + } + pb, err := codectypes.NewAnyWithValue(pm) + require.NoError(t, err) + return pb +} diff --git a/tests/e2e/auth/suite.go b/tests/e2e/auth/suite.go index 544fef1683b4..31dca150f87e 100644 --- a/tests/e2e/auth/suite.go +++ b/tests/e2e/auth/suite.go @@ -357,7 +357,6 @@ func (s *E2ETestSuite) TestCLIQueryTxCmdByHash() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := authcli.QueryTxCmd() clientCtx := val.GetClientCtx() @@ -490,7 +489,6 @@ func (s *E2ETestSuite) TestCLIQueryTxCmdByEvents() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := authcli.QueryTxCmd() clientCtx := val.GetClientCtx() @@ -570,7 +568,6 @@ func (s *E2ETestSuite) TestCLIQueryTxsCmdByEvents() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := authcli.QueryTxsByEventsCmd() clientCtx := val.GetClientCtx() @@ -1503,7 +1500,6 @@ func (s *E2ETestSuite) TestAuxSigner() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { _, err := govtestutil.MsgSubmitLegacyProposal( val.GetClientCtx(), @@ -1730,7 +1726,6 @@ func (s *E2ETestSuite) TestAuxToFeeWithTips() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { res, err := govtestutil.MsgSubmitLegacyProposal( val.GetClientCtx(), diff --git a/tests/e2e/authz/grpc.go b/tests/e2e/authz/grpc.go index e8b9c3487e25..d06c85bb024c 100644 --- a/tests/e2e/authz/grpc.go +++ b/tests/e2e/authz/grpc.go @@ -63,7 +63,6 @@ func (s *E2ETestSuite) TestQueryGrantGRPC() { }, } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { resp, _ := testutil.GetRequest(tc.url) require := s.Require() @@ -151,7 +150,6 @@ func (s *E2ETestSuite) TestQueryGrantsGRPC() { }, } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { tc.preRun() resp, err := testutil.GetRequest(tc.url) diff --git a/tests/e2e/authz/tx.go b/tests/e2e/authz/tx.go index 811cdf51ded5..bf8757c0777b 100644 --- a/tests/e2e/authz/tx.go +++ b/tests/e2e/authz/tx.go @@ -305,7 +305,6 @@ func (s *E2ETestSuite) TestNewExecGenericAuthorized() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := cli.NewCmdExecAuthorization() clientCtx := val.GetClientCtx() @@ -415,7 +414,6 @@ func (s *E2ETestSuite) TestNewExecGrantAuthorized() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := cli.NewCmdExecAuthorization() clientCtx := val.GetClientCtx() @@ -619,7 +617,6 @@ func (s *E2ETestSuite) TestExecDelegateAuthorization() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := cli.NewCmdExecAuthorization() clientCtx := val.GetClientCtx() @@ -686,7 +683,6 @@ func (s *E2ETestSuite) TestExecDelegateAuthorization() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := cli.NewCmdExecAuthorization() clientCtx := val.GetClientCtx() @@ -841,7 +837,6 @@ func (s *E2ETestSuite) TestExecUndelegateAuthorization() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := cli.NewCmdExecAuthorization() clientCtx := val.GetClientCtx() @@ -909,7 +904,6 @@ func (s *E2ETestSuite) TestExecUndelegateAuthorization() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := cli.NewCmdExecAuthorization() clientCtx := val.GetClientCtx() diff --git a/tests/e2e/client/grpc/cmtservice/service_test.go b/tests/e2e/client/grpc/cmtservice/service_test.go index a08c77ce4d1c..e4177a11edfb 100644 --- a/tests/e2e/client/grpc/cmtservice/service_test.go +++ b/tests/e2e/client/grpc/cmtservice/service_test.go @@ -154,7 +154,6 @@ func (s *E2ETestSuite) TestLatestValidatorSet_GRPC() { {"with pagination", &cmtservice.GetLatestValidatorSetRequest{Pagination: &qtypes.PageRequest{Offset: 0, Limit: uint64(len(vals))}}, false, ""}, } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { grpcRes, err := s.queryClient.GetLatestValidatorSet(context.Background(), tc.req) if tc.expErr { @@ -185,7 +184,6 @@ func (s *E2ETestSuite) TestLatestValidatorSet_GRPCGateway() { {"with pagination", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/latest?pagination.offset=0&pagination.limit=2", vals[0].GetAPIAddress()), false, ""}, } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { res, err := testutil.GetRequest(tc.url) s.Require().NoError(err) @@ -218,7 +216,6 @@ func (s *E2ETestSuite) TestValidatorSetByHeight_GRPC() { {"with pagination", &cmtservice.GetValidatorSetByHeightRequest{Height: 1, Pagination: &qtypes.PageRequest{Offset: 0, Limit: 1}}, false, ""}, } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { grpcRes, err := s.queryClient.GetValidatorSetByHeight(context.Background(), tc.req) if tc.expErr { @@ -247,7 +244,6 @@ func (s *E2ETestSuite) TestValidatorSetByHeight_GRPCGateway() { {"with pagination", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/%d?pagination.offset=0&pagination.limit=2", vals[0].GetAPIAddress(), 1), false, ""}, } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { res, err := testutil.GetRequest(tc.url) s.Require().NoError(err) @@ -326,8 +322,6 @@ func (s *E2ETestSuite) TestABCIQuery() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { res, err := s.queryClient.ABCIQuery(context.Background(), tc.req) if tc.expectErr { diff --git a/tests/e2e/distribution/grpc_query_suite.go b/tests/e2e/distribution/grpc_query_suite.go index 4a5a2c3475b8..991567abfb4e 100644 --- a/tests/e2e/distribution/grpc_query_suite.go +++ b/tests/e2e/distribution/grpc_query_suite.go @@ -64,7 +64,7 @@ func (s *GRPCQueryTestSuite) TestQueryParamsGRPC() { } for _, tc := range testCases { - tc := tc + resp, err := sdktestutil.GetRequest(tc.url) s.Run(tc.name, func() { s.Require().NoError(err) @@ -99,7 +99,7 @@ func (s *GRPCQueryTestSuite) TestQueryValidatorDistributionInfoGRPC() { } for _, tc := range testCases { - tc := tc + resp, err := sdktestutil.GetRequest(tc.url) s.Run(tc.name, func() { if tc.expErr { @@ -152,7 +152,7 @@ func (s *GRPCQueryTestSuite) TestQueryOutstandingRewardsGRPC() { } for _, tc := range testCases { - tc := tc + resp, err := sdktestutil.GetRequestWithHeaders(tc.url, tc.headers) s.Run(tc.name, func() { if tc.expErr { @@ -206,7 +206,7 @@ func (s *GRPCQueryTestSuite) TestQueryValidatorCommissionGRPC() { } for _, tc := range testCases { - tc := tc + resp, err := sdktestutil.GetRequestWithHeaders(tc.url, tc.headers) s.Run(tc.name, func() { if tc.expErr { @@ -264,7 +264,7 @@ func (s *GRPCQueryTestSuite) TestQuerySlashesGRPC() { } for _, tc := range testCases { - tc := tc + resp, err := sdktestutil.GetRequest(tc.url) s.Run(tc.name, func() { @@ -340,7 +340,7 @@ func (s *GRPCQueryTestSuite) TestQueryDelegatorRewardsGRPC() { } for _, tc := range testCases { - tc := tc + resp, err := sdktestutil.GetRequestWithHeaders(tc.url, tc.headers) s.Run(tc.name, func() { @@ -392,7 +392,7 @@ func (s *GRPCQueryTestSuite) TestQueryDelegatorValidatorsGRPC() { } for _, tc := range testCases { - tc := tc + resp, err := sdktestutil.GetRequest(tc.url) s.Run(tc.name, func() { @@ -444,7 +444,7 @@ func (s *GRPCQueryTestSuite) TestQueryWithdrawAddressGRPC() { } for _, tc := range testCases { - tc := tc + resp, err := sdktestutil.GetRequest(tc.url) s.Run(tc.name, func() { diff --git a/tests/e2e/gov/tx.go b/tests/e2e/gov/tx.go index 3806e54a8823..9d6f84ce15aa 100644 --- a/tests/e2e/gov/tx.go +++ b/tests/e2e/gov/tx.go @@ -164,8 +164,6 @@ func (s *E2ETestSuite) TestNewCmdSubmitProposal() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { cmd := cli.NewCmdSubmitProposal() clientCtx := val.GetClientCtx() @@ -260,8 +258,6 @@ func (s *E2ETestSuite) TestNewCmdSubmitLegacyProposal() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { cmd := cli.NewCmdSubmitLegacyProposal() clientCtx := val.GetClientCtx() @@ -357,7 +353,6 @@ func (s *E2ETestSuite) TestNewCmdWeightedVote() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := cli.NewCmdWeightedVote() clientCtx := val.GetClientCtx() diff --git a/tests/e2e/tx/service_test.go b/tests/e2e/tx/service_test.go index b9e875f1173e..f0e4e527664c 100644 --- a/tests/e2e/tx/service_test.go +++ b/tests/e2e/tx/service_test.go @@ -175,7 +175,6 @@ func (s *E2ETestSuite) TestSimulateTx_GRPC() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { // Broadcast the tx via gRPC via the validator's clientCtx (which goes // through Tendermint). @@ -506,7 +505,6 @@ func (s *E2ETestSuite) TestBroadcastTx_GRPC() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { // Broadcast the tx via gRPC via the validator's clientCtx (which goes // through Tendermint). @@ -772,7 +770,6 @@ func (s *E2ETestSuite) TestTxEncode_GRPC() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { res, err := s.queryClient.TxEncode(context.Background(), tc.req) if tc.expErr { @@ -852,7 +849,6 @@ func (s *E2ETestSuite) TestTxDecode_GRPC() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { res, err := s.queryClient.TxDecode(context.Background(), tc.req) if tc.expErr { @@ -963,7 +959,6 @@ func (s *E2ETestSuite) TestTxEncodeAmino_GRPC() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { res, err := s.queryClient.TxEncodeAmino(context.Background(), tc.req) if tc.expErr { @@ -1049,7 +1044,6 @@ func (s *E2ETestSuite) TestTxDecodeAmino_GRPC() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { res, err := s.queryClient.TxDecodeAmino(context.Background(), tc.req) if tc.expErr { diff --git a/tests/go.mod b/tests/go.mod index 9f834034fab6..9c91191473f3 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -5,7 +5,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/depinject v1.0.0 cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 @@ -13,7 +13,7 @@ require ( cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc cosmossdk.io/x/evidence v0.0.0-20230613133644-0a778132a60f cosmossdk.io/x/feegrant v0.0.0-20230613133644-0a778132a60f - cosmossdk.io/x/nft v0.0.0-20230613133644-0a778132a60f + cosmossdk.io/x/nft v0.0.0-20230613133644-0a778132a60f // indirect cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 cosmossdk.io/x/tx v0.13.4 cosmossdk.io/x/upgrade v0.0.0-20230613133644-0a778132a60f @@ -34,7 +34,8 @@ require ( require ( cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 - cosmossdk.io/x/accounts v0.0.0-20240226161501-23359a0b6d91 + cosmossdk.io/x/accounts v0.0.0-20240913065641-0064ccbce64e + cosmossdk.io/x/accounts/defaults/base v0.0.0-00010101000000-000000000000 cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 cosmossdk.io/x/accounts/defaults/multisig v0.0.0-00010101000000-000000000000 cosmossdk.io/x/authz v0.0.0-00010101000000-000000000000 @@ -65,7 +66,7 @@ require ( cloud.google.com/go/storage v1.43.0 // indirect cosmossdk.io/client/v2 v2.0.0-20230630094428-02b760776860 // indirect cosmossdk.io/errors v1.0.1 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/x/circuit v0.0.0-20230613133644-0a778132a60f // indirect cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 // indirect filippo.io/edwards25519 v1.1.0 // indirect @@ -173,7 +174,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -239,6 +240,7 @@ replace ( cosmossdk.io/core/testing => ../core/testing cosmossdk.io/store => ../store cosmossdk.io/x/accounts => ../x/accounts + cosmossdk.io/x/accounts/defaults/base => ../x/accounts/defaults/base cosmossdk.io/x/accounts/defaults/lockup => ../x/accounts/defaults/lockup cosmossdk.io/x/accounts/defaults/multisig => ../x/accounts/defaults/multisig cosmossdk.io/x/authz => ../x/authz diff --git a/tests/go.sum b/tests/go.sum index 2427554385a3..2424b6d5da22 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -192,8 +192,8 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -202,8 +202,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= @@ -710,8 +710,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/tests/integration/auth/client/cli/suite_test.go b/tests/integration/auth/client/cli/suite_test.go index b16d469ec445..ea2b929c5b31 100644 --- a/tests/integration/auth/client/cli/suite_test.go +++ b/tests/integration/auth/client/cli/suite_test.go @@ -274,7 +274,6 @@ func (s *CLITestSuite) TestCLIQueryTxCmdByHash() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := authcli.QueryTxCmd() cmd.SetArgs(tc.args) @@ -340,7 +339,6 @@ func (s *CLITestSuite) TestCLIQueryTxCmdByEvents() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := authcli.QueryTxCmd() cmd.SetArgs(tc.args) @@ -383,7 +381,6 @@ func (s *CLITestSuite) TestCLIQueryTxsCmdByEvents() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := authcli.QueryTxsByEventsCmd() @@ -1019,7 +1016,6 @@ func (s *CLITestSuite) TestAuxSigner() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { _, err := govtestutil.MsgSubmitLegacyProposal( s.clientCtx, @@ -1238,7 +1234,6 @@ func (s *CLITestSuite) TestAuxToFeeWithTips() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { res, err := govtestutil.MsgSubmitLegacyProposal( s.clientCtx, diff --git a/tests/integration/auth/keeper/accounts_retro_compatibility_test.go b/tests/integration/auth/keeper/accounts_retro_compatibility_test.go new file mode 100644 index 000000000000..361dab20c815 --- /dev/null +++ b/tests/integration/auth/keeper/accounts_retro_compatibility_test.go @@ -0,0 +1,157 @@ +package keeper_test + +import ( + "context" + "testing" + + gogotypes "github.com/cosmos/gogoproto/types" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "cosmossdk.io/x/accounts/accountstd" + basev1 "cosmossdk.io/x/accounts/defaults/base/v1" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +var _ accountstd.Interface = mockRetroCompatAccount{} + +type mockRetroCompatAccount struct { + retroCompat *authtypes.QueryLegacyAccountResponse + address []byte +} + +func (m mockRetroCompatAccount) RegisterInitHandler(builder *accountstd.InitBuilder) { + accountstd.RegisterInitHandler(builder, func(ctx context.Context, req *gogotypes.Empty) (*gogotypes.Empty, error) { + return &gogotypes.Empty{}, nil + }) +} + +func (m mockRetroCompatAccount) RegisterExecuteHandlers(_ *accountstd.ExecuteBuilder) {} + +func (m mockRetroCompatAccount) RegisterQueryHandlers(builder *accountstd.QueryBuilder) { + if m.retroCompat == nil { + return + } + accountstd.RegisterQueryHandler(builder, func(ctx context.Context, req *authtypes.QueryLegacyAccount) (*authtypes.QueryLegacyAccountResponse, error) { + return m.retroCompat, nil + }) +} + +func TestAuthToAccountsGRPCCompat(t *testing.T) { + valid := &mockRetroCompatAccount{ + retroCompat: &authtypes.QueryLegacyAccountResponse{ + Account: &codectypes.Any{}, + Info: &authtypes.BaseAccount{ + Address: "test", + PubKey: nil, + AccountNumber: 10, + Sequence: 20, + }, + }, + } + + noInfo := &mockRetroCompatAccount{ + retroCompat: &authtypes.QueryLegacyAccountResponse{ + Account: &codectypes.Any{}, + }, + } + noImplement := &mockRetroCompatAccount{ + retroCompat: nil, + } + + accs := map[string]accountstd.Interface{ + "valid": valid, + "no_info": noInfo, + "no_implement": noImplement, + } + + f := initFixture(t, accs) + + // init three accounts + for n, a := range accs { + _, addr, err := f.accountsKeeper.Init(f.ctx, n, []byte("me"), &gogotypes.Empty{}, nil) + require.NoError(t, err) + a.(*mockRetroCompatAccount).address = addr + } + + qs := authkeeper.NewQueryServer(f.authKeeper) + + t.Run("account supports info and account query", func(t *testing.T) { + infoResp, err := qs.AccountInfo(f.ctx, &authtypes.QueryAccountInfoRequest{ + Address: f.mustAddr(valid.address), + }) + require.NoError(t, err) + require.Equal(t, infoResp.Info, valid.retroCompat.Info) + + accountResp, err := qs.Account(f.ctx, &authtypes.QueryAccountRequest{ + Address: f.mustAddr(noInfo.address), + }) + require.NoError(t, err) + require.Equal(t, accountResp.Account, valid.retroCompat.Account) + }) + + t.Run("account only supports account query, not info", func(t *testing.T) { + _, err := qs.AccountInfo(f.ctx, &authtypes.QueryAccountInfoRequest{ + Address: f.mustAddr(noInfo.address), + }) + require.Error(t, err) + require.Equal(t, status.Code(err), codes.NotFound) + + resp, err := qs.Account(f.ctx, &authtypes.QueryAccountRequest{ + Address: f.mustAddr(noInfo.address), + }) + require.NoError(t, err) + require.Equal(t, resp.Account, valid.retroCompat.Account) + }) + + t.Run("account does not support any retro compat", func(t *testing.T) { + _, err := qs.AccountInfo(f.ctx, &authtypes.QueryAccountInfoRequest{ + Address: f.mustAddr(noImplement.address), + }) + require.Error(t, err) + require.Equal(t, status.Code(err), codes.NotFound) + + _, err = qs.Account(f.ctx, &authtypes.QueryAccountRequest{ + Address: f.mustAddr(noImplement.address), + }) + + require.Error(t, err) + require.Equal(t, status.Code(err), codes.NotFound) + }) +} + +func TestAccountsBaseAccountRetroCompat(t *testing.T) { + f := initFixture(t, nil) + // init a base acc + anyPk, err := codectypes.NewAnyWithValue(secp256k1.GenPrivKey().PubKey()) + require.NoError(t, err) + + // we init two accounts to have account num not be zero. + _, _, err = f.accountsKeeper.Init(f.ctx, "base", []byte("me"), &basev1.MsgInit{PubKey: anyPk}, nil) + require.NoError(t, err) + + _, addr, err := f.accountsKeeper.Init(f.ctx, "base", []byte("me"), &basev1.MsgInit{PubKey: anyPk}, nil) + require.NoError(t, err) + + // try to query it via auth + qs := authkeeper.NewQueryServer(f.authKeeper) + + r, err := qs.Account(f.ctx, &authtypes.QueryAccountRequest{ + Address: f.mustAddr(addr), + }) + require.NoError(t, err) + require.NotNil(t, r.Account) + + info, err := qs.AccountInfo(f.ctx, &authtypes.QueryAccountInfoRequest{ + Address: f.mustAddr(addr), + }) + require.NoError(t, err) + require.NotNil(t, info.Info) + require.Equal(t, info.Info.PubKey, anyPk) + require.Equal(t, info.Info.AccountNumber, uint64(1)) +} diff --git a/tests/integration/auth/keeper/fixture_test.go b/tests/integration/auth/keeper/fixture_test.go new file mode 100644 index 000000000000..45514c0cdba7 --- /dev/null +++ b/tests/integration/auth/keeper/fixture_test.go @@ -0,0 +1,143 @@ +package keeper_test + +import ( + "testing" + + "gotest.tools/v3/assert" + + "cosmossdk.io/core/appmodule" + "cosmossdk.io/log" + storetypes "cosmossdk.io/store/types" + "cosmossdk.io/x/accounts" + "cosmossdk.io/x/accounts/accountstd" + baseaccount "cosmossdk.io/x/accounts/defaults/base" + accountsv1 "cosmossdk.io/x/accounts/v1" + "cosmossdk.io/x/bank" + bankkeeper "cosmossdk.io/x/bank/keeper" + banktypes "cosmossdk.io/x/bank/types" + minttypes "cosmossdk.io/x/mint/types" + "cosmossdk.io/x/tx/signing" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + addresscodec "github.com/cosmos/cosmos-sdk/codec/address" + codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil/integration" + sdk "github.com/cosmos/cosmos-sdk/types" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + "github.com/cosmos/cosmos-sdk/x/auth" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +type fixture struct { + app *integration.App + + cdc codec.Codec + ctx sdk.Context + + authKeeper authkeeper.AccountKeeper + accountsKeeper accounts.Keeper + bankKeeper bankkeeper.Keeper +} + +func (f fixture) mustAddr(address []byte) string { + s, _ := f.authKeeper.AddressCodec().BytesToString(address) + return s +} + +func initFixture(t *testing.T, extraAccs map[string]accountstd.Interface) *fixture { + t.Helper() + keys := storetypes.NewKVStoreKeys( + authtypes.StoreKey, banktypes.StoreKey, accounts.StoreKey, + ) + encodingCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{}, bank.AppModule{}, accounts.AppModule{}) + cdc := encodingCfg.Codec + + logger := log.NewTestLogger(t) + cms := integration.CreateMultiStore(keys, logger) + + newCtx := sdk.NewContext(cms, true, logger) + + router := baseapp.NewMsgServiceRouter() + queryRouter := baseapp.NewGRPCQueryRouter() + + handler := directHandler{} + account := baseaccount.NewAccount("base", signing.NewHandlerMap(handler), baseaccount.WithSecp256K1PubKey()) + + var accs []accountstd.AccountCreatorFunc + for name, acc := range extraAccs { + f := accountstd.AddAccount(name, func(_ accountstd.Dependencies) (accountstd.Interface, error) { + return acc, nil + }) + accs = append(accs, f) + } + accountsKeeper, err := accounts.NewKeeper( + cdc, + runtime.NewEnvironment(runtime.NewKVStoreService(keys[accounts.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(queryRouter), runtime.EnvWithMsgRouterService(router)), + addresscodec.NewBech32Codec("cosmos"), + cdc.InterfaceRegistry(), + append(accs, account)..., + ) + assert.NilError(t, err) + accountsv1.RegisterQueryServer(queryRouter, accounts.NewQueryServer(accountsKeeper)) + + authority := authtypes.NewModuleAddress("gov") + + authKeeper := authkeeper.NewAccountKeeper( + runtime.NewEnvironment(runtime.NewKVStoreService(keys[authtypes.StoreKey]), log.NewNopLogger()), + cdc, + authtypes.ProtoBaseAccount, + accountsKeeper, + map[string][]string{minttypes.ModuleName: {authtypes.Minter}}, + addresscodec.NewBech32Codec(sdk.Bech32MainPrefix), + sdk.Bech32MainPrefix, + authority.String(), + ) + + blockedAddresses := map[string]bool{ + authKeeper.GetAuthority(): false, + } + bankKeeper := bankkeeper.NewBaseKeeper( + runtime.NewEnvironment(runtime.NewKVStoreService(keys[banktypes.StoreKey]), log.NewNopLogger()), + cdc, + authKeeper, + blockedAddresses, + authority.String(), + ) + + params := banktypes.DefaultParams() + assert.NilError(t, bankKeeper.SetParams(newCtx, params)) + + accountsModule := accounts.NewAppModule(cdc, accountsKeeper) + authModule := auth.NewAppModule(cdc, authKeeper, accountsKeeper, authsims.RandomGenesisAccounts, nil) + bankModule := bank.NewAppModule(cdc, bankKeeper, authKeeper) + + integrationApp := integration.NewIntegrationApp(newCtx, logger, keys, cdc, + encodingCfg.InterfaceRegistry.SigningContext().AddressCodec(), + encodingCfg.InterfaceRegistry.SigningContext().ValidatorAddressCodec(), + map[string]appmodule.AppModule{ + accounts.ModuleName: accountsModule, + authtypes.ModuleName: authModule, + banktypes.ModuleName: bankModule, + }, router, queryRouter) + + authtypes.RegisterInterfaces(cdc.InterfaceRegistry()) + banktypes.RegisterInterfaces(cdc.InterfaceRegistry()) + + authtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), authkeeper.NewMsgServerImpl(authKeeper)) + authtypes.RegisterQueryServer(integrationApp.QueryHelper(), authkeeper.NewQueryServer(authKeeper)) + + banktypes.RegisterMsgServer(router, bankkeeper.NewMsgServerImpl(bankKeeper)) + + return &fixture{ + app: integrationApp, + cdc: cdc, + ctx: newCtx, + accountsKeeper: accountsKeeper, + authKeeper: authKeeper, + bankKeeper: bankKeeper, + } +} diff --git a/tests/integration/auth/keeper/msg_server_test.go b/tests/integration/auth/keeper/msg_server_test.go index d9985add6a61..076f33620508 100644 --- a/tests/integration/auth/keeper/msg_server_test.go +++ b/tests/integration/auth/keeper/msg_server_test.go @@ -9,46 +9,18 @@ import ( "gotest.tools/v3/assert" signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1" - "cosmossdk.io/core/appmodule" - "cosmossdk.io/log" sdkmath "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" - "cosmossdk.io/x/accounts" - baseaccount "cosmossdk.io/x/accounts/defaults/base" - "cosmossdk.io/x/bank" - bankkeeper "cosmossdk.io/x/bank/keeper" "cosmossdk.io/x/bank/testutil" banktypes "cosmossdk.io/x/bank/types" - minttypes "cosmossdk.io/x/mint/types" "cosmossdk.io/x/tx/signing" - "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/codec" - addresscodec "github.com/cosmos/cosmos-sdk/codec/address" - codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/runtime" "github.com/cosmos/cosmos-sdk/testutil/integration" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" - moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" - "github.com/cosmos/cosmos-sdk/x/auth" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) -type fixture struct { - app *integration.App - - cdc codec.Codec - ctx sdk.Context - - authKeeper authkeeper.AccountKeeper - accountsKeeper accounts.Keeper - bankKeeper bankkeeper.Keeper -} - var _ signing.SignModeHandler = directHandler{} type directHandler struct{} @@ -61,94 +33,9 @@ func (s directHandler) GetSignBytes(_ context.Context, _ signing.SignerData, _ s panic("not implemented") } -func initFixture(t *testing.T) *fixture { - t.Helper() - keys := storetypes.NewKVStoreKeys( - authtypes.StoreKey, banktypes.StoreKey, accounts.StoreKey, - ) - encodingCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{}, bank.AppModule{}, accounts.AppModule{}) - cdc := encodingCfg.Codec - - logger := log.NewTestLogger(t) - cms := integration.CreateMultiStore(keys, logger) - - newCtx := sdk.NewContext(cms, true, logger) - - router := baseapp.NewMsgServiceRouter() - queryRouter := baseapp.NewGRPCQueryRouter() - - handler := directHandler{} - account := baseaccount.NewAccount("base", signing.NewHandlerMap(handler), baseaccount.WithSecp256K1PubKey()) - accountsKeeper, err := accounts.NewKeeper( - cdc, - runtime.NewEnvironment(runtime.NewKVStoreService(keys[accounts.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(queryRouter), runtime.EnvWithMsgRouterService(router)), - addresscodec.NewBech32Codec("cosmos"), - cdc.InterfaceRegistry(), - account, - ) - assert.NilError(t, err) - - authority := authtypes.NewModuleAddress("gov") - - authKeeper := authkeeper.NewAccountKeeper( - runtime.NewEnvironment(runtime.NewKVStoreService(keys[authtypes.StoreKey]), log.NewNopLogger()), - cdc, - authtypes.ProtoBaseAccount, - accountsKeeper, - map[string][]string{minttypes.ModuleName: {authtypes.Minter}}, - addresscodec.NewBech32Codec(sdk.Bech32MainPrefix), - sdk.Bech32MainPrefix, - authority.String(), - ) - - blockedAddresses := map[string]bool{ - authKeeper.GetAuthority(): false, - } - bankKeeper := bankkeeper.NewBaseKeeper( - runtime.NewEnvironment(runtime.NewKVStoreService(keys[banktypes.StoreKey]), log.NewNopLogger()), - cdc, - authKeeper, - blockedAddresses, - authority.String(), - ) - - params := banktypes.DefaultParams() - assert.NilError(t, bankKeeper.SetParams(newCtx, params)) - - accountsModule := accounts.NewAppModule(cdc, accountsKeeper) - authModule := auth.NewAppModule(cdc, authKeeper, accountsKeeper, authsims.RandomGenesisAccounts, nil) - bankModule := bank.NewAppModule(cdc, bankKeeper, authKeeper) - - integrationApp := integration.NewIntegrationApp(newCtx, logger, keys, cdc, - encodingCfg.InterfaceRegistry.SigningContext().AddressCodec(), - encodingCfg.InterfaceRegistry.SigningContext().ValidatorAddressCodec(), - map[string]appmodule.AppModule{ - accounts.ModuleName: accountsModule, - authtypes.ModuleName: authModule, - banktypes.ModuleName: bankModule, - }, router, queryRouter) - - authtypes.RegisterInterfaces(cdc.InterfaceRegistry()) - banktypes.RegisterInterfaces(cdc.InterfaceRegistry()) - - authtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), authkeeper.NewMsgServerImpl(authKeeper)) - authtypes.RegisterQueryServer(integrationApp.QueryHelper(), authkeeper.NewQueryServer(authKeeper)) - - banktypes.RegisterMsgServer(router, bankkeeper.NewMsgServerImpl(bankKeeper)) - - return &fixture{ - app: integrationApp, - cdc: cdc, - ctx: newCtx, - accountsKeeper: accountsKeeper, - authKeeper: authKeeper, - bankKeeper: bankKeeper, - } -} - func TestAsyncExec(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, nil) addrs := simtestutil.CreateIncrementalAccounts(2) coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))) @@ -250,7 +137,6 @@ func TestAsyncExec(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { res, err := f.app.RunMsg( tc.req, diff --git a/tests/integration/bank/keeper/deterministic_test.go b/tests/integration/bank/keeper/deterministic_test.go index 575fdaead315..7233a4d0ee86 100644 --- a/tests/integration/bank/keeper/deterministic_test.go +++ b/tests/integration/bank/keeper/deterministic_test.go @@ -200,7 +200,9 @@ func TestGRPCQueryAllBalances(t *testing.T) { for i := 0; i < numCoins; i++ { coin := getCoin(rt) - + if exists, _ := coins.Find(coin.Denom); exists { + t.Skip("duplicate denom") + } // NewCoins sorts the denoms coins = sdk.NewCoins(append(coins, coin)...) } diff --git a/tests/integration/distribution/cli_tx_test.go b/tests/integration/distribution/cli_tx_test.go index 06f3012128db..0eb26d978c2f 100644 --- a/tests/integration/distribution/cli_tx_test.go +++ b/tests/integration/distribution/cli_tx_test.go @@ -111,8 +111,6 @@ func (s *CLITestSuite) TestTxWithdrawAllRewardsCmd() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { cmd := cli.NewWithdrawAllRewardsCmd() diff --git a/tests/integration/distribution/keeper/msg_server_test.go b/tests/integration/distribution/keeper/msg_server_test.go index a7be5653566a..7ab94c01a3e1 100644 --- a/tests/integration/distribution/keeper/msg_server_test.go +++ b/tests/integration/distribution/keeper/msg_server_test.go @@ -146,8 +146,8 @@ func initFixture(t *testing.T) *fixture { authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil) bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper) - distrModule := distribution.NewAppModule(cdc, distrKeeper, accountKeeper, bankKeeper, stakingKeeper) + stakingModule := staking.NewAppModule(cdc, stakingKeeper) + distrModule := distribution.NewAppModule(cdc, distrKeeper, stakingKeeper) poolModule := protocolpool.NewAppModule(cdc, poolKeeper, accountKeeper, bankKeeper) consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) @@ -331,7 +331,6 @@ func TestMsgWithdrawDelegatorReward(t *testing.T) { height := f.app.LastBlockHeight() for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { res, err := f.app.RunMsg( tc.msg, @@ -469,7 +468,6 @@ func TestMsgSetWithdrawAddress(t *testing.T) { }, } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { tc.preRun() res, err := f.app.RunMsg( @@ -566,7 +564,6 @@ func TestMsgWithdrawValidatorCommission(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { res, err := f.app.RunMsg( tc.msg, @@ -600,7 +597,6 @@ func TestMsgWithdrawValidatorCommission(t *testing.T) { }, remainder.Commission) } }) - } } @@ -666,7 +662,6 @@ func TestMsgFundCommunityPool(t *testing.T) { }, } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { res, err := f.app.RunMsg( tc.msg, @@ -808,7 +803,6 @@ func TestMsgUpdateParams(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { res, err := f.app.RunMsg( tc.msg, @@ -891,7 +885,6 @@ func TestMsgCommunityPoolSpend(t *testing.T) { }, } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { res, err := f.app.RunMsg( tc.msg, @@ -992,7 +985,6 @@ func TestMsgDepositValidatorRewardsPool(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { res, err := f.app.RunMsg( tc.msg, diff --git a/tests/integration/evidence/keeper/infraction_test.go b/tests/integration/evidence/keeper/infraction_test.go index b666bd3fcb5b..745407688cb2 100644 --- a/tests/integration/evidence/keeper/infraction_test.go +++ b/tests/integration/evidence/keeper/infraction_test.go @@ -161,7 +161,7 @@ func initFixture(tb testing.TB) *fixture { authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil) bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper) + stakingModule := staking.NewAppModule(cdc, stakingKeeper) slashingModule := slashing.NewAppModule(cdc, slashingKeeper, accountKeeper, bankKeeper, stakingKeeper, cdc.InterfaceRegistry(), cometInfoService) evidenceModule := evidence.NewAppModule(cdc, *evidenceKeeper, cometInfoService) consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) diff --git a/tests/integration/genutil/genaccount_test.go b/tests/integration/genutil/genaccount_test.go index 739adda97d2b..1b1bd420e99e 100644 --- a/tests/integration/genutil/genaccount_test.go +++ b/tests/integration/genutil/genaccount_test.go @@ -72,7 +72,6 @@ func TestAddGenesisAccountCmd(t *testing.T) { } for _, tc := range tests { - tc := tc t.Run(tc.name, func(t *testing.T) { home := t.TempDir() logger := log.NewNopLogger() @@ -217,7 +216,6 @@ func TestBulkAddGenesisAccountCmd(t *testing.T) { } for _, tc := range tests { - tc := tc t.Run(tc.name, func(t *testing.T) { home := t.TempDir() logger := log.NewNopLogger() diff --git a/tests/integration/genutil/init_test.go b/tests/integration/genutil/init_test.go index 9116db0ce8fe..b49dbc6a7458 100644 --- a/tests/integration/genutil/init_test.go +++ b/tests/integration/genutil/init_test.go @@ -37,7 +37,7 @@ import ( ) var testMbm = module.NewManager( - staking.NewAppModule(makeCodec(), nil, nil, nil), + staking.NewAppModule(makeCodec(), nil), genutil.NewAppModule(makeCodec(), nil, nil, nil, nil, nil), ) @@ -61,7 +61,6 @@ func TestInitCmd(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { home := t.TempDir() logger := log.NewNopLogger() diff --git a/tests/integration/gov/keeper/keeper_test.go b/tests/integration/gov/keeper/keeper_test.go index da20fc9b2b98..f1f94f575d58 100644 --- a/tests/integration/gov/keeper/keeper_test.go +++ b/tests/integration/gov/keeper/keeper_test.go @@ -149,7 +149,7 @@ func initFixture(tb testing.TB) *fixture { authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil) bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper) + stakingModule := staking.NewAppModule(cdc, stakingKeeper) govModule := gov.NewAppModule(cdc, govKeeper, accountKeeper, bankKeeper, poolKeeper) consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) diff --git a/tests/integration/slashing/keeper/keeper_test.go b/tests/integration/slashing/keeper/keeper_test.go index a50dcac4fa05..e961dc68233d 100644 --- a/tests/integration/slashing/keeper/keeper_test.go +++ b/tests/integration/slashing/keeper/keeper_test.go @@ -126,7 +126,7 @@ func initFixture(tb testing.TB) *fixture { slashingKeeper := slashingkeeper.NewKeeper(runtime.NewEnvironment(runtime.NewKVStoreService(keys[slashingtypes.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(queryRouter), runtime.EnvWithMsgRouterService(msgRouter)), cdc, &codec.LegacyAmino{}, stakingKeeper, authority.String()) bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper) + stakingModule := staking.NewAppModule(cdc, stakingKeeper) slashingModule := slashing.NewAppModule(cdc, slashingKeeper, accountKeeper, bankKeeper, stakingKeeper, cdc.InterfaceRegistry(), cometInfoService) consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) diff --git a/tests/integration/staking/keeper/common_test.go b/tests/integration/staking/keeper/common_test.go index 26d0e217afaa..e3963efb7bb7 100644 --- a/tests/integration/staking/keeper/common_test.go +++ b/tests/integration/staking/keeper/common_test.go @@ -170,7 +170,7 @@ func initFixture(tb testing.TB) *fixture { authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil) bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper) + stakingModule := staking.NewAppModule(cdc, stakingKeeper) consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) integrationApp := integration.NewIntegrationApp(newCtx, logger, keys, cdc, diff --git a/tests/integration/staking/keeper/deterministic_test.go b/tests/integration/staking/keeper/deterministic_test.go index ca5f1047808d..4a15c7775a35 100644 --- a/tests/integration/staking/keeper/deterministic_test.go +++ b/tests/integration/staking/keeper/deterministic_test.go @@ -133,7 +133,7 @@ func initDeterministicFixture(t *testing.T) *deterministicFixture { authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil) bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper) + stakingModule := staking.NewAppModule(cdc, stakingKeeper) consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) integrationApp := integration.NewIntegrationApp(newCtx, logger, keys, cdc, diff --git a/tests/integration/staking/keeper/msg_server_test.go b/tests/integration/staking/keeper/msg_server_test.go index f5e4accc0073..7eb00bb97a97 100644 --- a/tests/integration/staking/keeper/msg_server_test.go +++ b/tests/integration/staking/keeper/msg_server_test.go @@ -163,8 +163,6 @@ func TestCancelUnbondingDelegation(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { _, err := msgServer.CancelUnbondingDelegation(ctx, &tc.req) if tc.exceptErr { diff --git a/tests/integration/staking/simulation/operations_test.go b/tests/integration/staking/simulation/operations_test.go deleted file mode 100644 index a5a6fbc41e14..000000000000 --- a/tests/integration/staking/simulation/operations_test.go +++ /dev/null @@ -1,443 +0,0 @@ -package simulation_test - -import ( - "math/big" - "math/rand" - "testing" - "time" - - abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" - cmttypes "github.com/cometbft/cometbft/types" - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/collections" - "cosmossdk.io/core/header" - "cosmossdk.io/depinject" - sdklog "cosmossdk.io/log" - "cosmossdk.io/math" - bankkeeper "cosmossdk.io/x/bank/keeper" - banktestutil "cosmossdk.io/x/bank/testutil" - distrkeeper "cosmossdk.io/x/distribution/keeper" - distrtypes "cosmossdk.io/x/distribution/types" - mintkeeper "cosmossdk.io/x/mint/keeper" - minttypes "cosmossdk.io/x/mint/types" - stakingkeeper "cosmossdk.io/x/staking/keeper" - "cosmossdk.io/x/staking/simulation" - "cosmossdk.io/x/staking/testutil" - "cosmossdk.io/x/staking/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec/address" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/tests/integration/staking" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" -) - -type SimTestSuite struct { - suite.Suite - - r *rand.Rand - txConfig client.TxConfig - accounts []simtypes.Account - ctx sdk.Context - app *runtime.App - bankKeeper bankkeeper.Keeper - accountKeeper authkeeper.AccountKeeper - distrKeeper distrkeeper.Keeper - stakingKeeper *stakingkeeper.Keeper - - encCfg moduletestutil.TestEncodingConfig -} - -func (s *SimTestSuite) SetupTest() { - sdk.DefaultPowerReduction = math.NewIntFromBigInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)) - - s.r = rand.New(rand.NewSource(1)) - accounts := simtypes.RandomAccounts(s.r, 4) - - // create genesis accounts - senderPrivKey := secp256k1.GenPrivKey() - acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0) - accs := []simtestutil.GenesisAccount{ - {GenesisAccount: acc, Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(100000000000000)))}, - } - - // create validator set with single validator - account := accounts[0] - cmtPk, err := cryptocodec.ToCmtPubKeyInterface(account.ConsKey.PubKey()) - require.NoError(s.T(), err) - validator := cmttypes.NewValidator(cmtPk, 1) - - startupCfg := simtestutil.DefaultStartUpConfig() - startupCfg.GenesisAccounts = accs - startupCfg.ValidatorSet = func() (*cmttypes.ValidatorSet, error) { - return cmttypes.NewValidatorSet([]*cmttypes.Validator{validator}), nil - } - - var ( - accountKeeper authkeeper.AccountKeeper - mintKeeper mintkeeper.Keeper - bankKeeper bankkeeper.Keeper - distrKeeper distrkeeper.Keeper - stakingKeeper *stakingkeeper.Keeper - ) - - cfg := depinject.Configs( - staking.AppConfig, - depinject.Supply(sdklog.NewNopLogger()), - ) - - app, err := simtestutil.SetupWithConfiguration(cfg, startupCfg, &s.txConfig, &bankKeeper, &accountKeeper, &mintKeeper, &distrKeeper, &stakingKeeper) - require.NoError(s.T(), err) - - ctx := app.BaseApp.NewContext(false) - s.Require().NoError(mintKeeper.Params.Set(ctx, minttypes.DefaultParams())) - s.Require().NoError(mintKeeper.Minter.Set(ctx, minttypes.DefaultInitialMinter())) - - initAmt := stakingKeeper.TokensFromConsensusPower(ctx, 200) - initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) - - s.accounts = accounts - // remove genesis validator account - // add coins to the accounts - for _, account := range accounts[1:] { - acc := accountKeeper.NewAccountWithAddress(ctx, account.Address) - accountKeeper.SetAccount(ctx, acc) - s.Require().NoError(banktestutil.FundAccount(ctx, bankKeeper, account.Address, initCoins)) - } - - s.accountKeeper = accountKeeper - s.bankKeeper = bankKeeper - s.distrKeeper = distrKeeper - s.stakingKeeper = stakingKeeper - s.ctx = ctx - s.app = app -} - -// TestWeightedOperations tests the weights of the operations. -func (s *SimTestSuite) TestWeightedOperations() { - require := s.Require() - - s.ctx.WithChainID("test-chain") - - cdc := s.encCfg.Codec - appParams := make(simtypes.AppParams) - - weightedOps := simulation.WeightedOperations(appParams, cdc, s.txConfig, s.accountKeeper, - s.bankKeeper, s.stakingKeeper, - ) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {simulation.DefaultWeightMsgCreateValidator, types.ModuleName, sdk.MsgTypeURL(&types.MsgCreateValidator{})}, - {simulation.DefaultWeightMsgEditValidator, types.ModuleName, sdk.MsgTypeURL(&types.MsgEditValidator{})}, - {simulation.DefaultWeightMsgDelegate, types.ModuleName, sdk.MsgTypeURL(&types.MsgDelegate{})}, - {simulation.DefaultWeightMsgUndelegate, types.ModuleName, sdk.MsgTypeURL(&types.MsgUndelegate{})}, - {simulation.DefaultWeightMsgBeginRedelegate, types.ModuleName, sdk.MsgTypeURL(&types.MsgBeginRedelegate{})}, - {simulation.DefaultWeightMsgCancelUnbondingDelegation, types.ModuleName, sdk.MsgTypeURL(&types.MsgCancelUnbondingDelegation{})}, - {simulation.DefaultWeightMsgRotateConsPubKey, types.ModuleName, sdk.MsgTypeURL(&types.MsgRotateConsPubKey{})}, - } - - for i, w := range weightedOps { - operationMsg, _, _ := w.Op()(s.r, s.app.BaseApp, s.ctx, s.accounts, s.ctx.ChainID()) - // require.NoError(t, err) // TODO check if it should be NoError - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - require.Equal(expected[i].weight, w.Weight(), "weight should be the same") - require.Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - require.Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -// TestSimulateMsgCreateValidator tests the normal scenario of a valid message of type TypeMsgCreateValidator. -// Abonormal scenarios, where the message are created by an errors are not tested here. -func (s *SimTestSuite) TestSimulateMsgCreateValidator() { - require := s.Require() - _, err := s.app.FinalizeBlock(&abci.FinalizeBlockRequest{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash}) - require.NoError(err) - // execute operation - op := simulation.SimulateMsgCreateValidator(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper) - operationMsg, futureOperations, err := op(s.r, s.app.BaseApp, s.ctx, s.accounts[1:], "") - require.NoError(err) - - var msg types.MsgCreateValidator - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - require.True(operationMsg.OK) - require.Equal(sdk.MsgTypeURL(&types.MsgCreateValidator{}), sdk.MsgTypeURL(&msg)) - valaddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress) - require.NoError(err) - require.Equal("cosmos1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7u4x9a0", sdk.AccAddress(valaddr).String()) - require.Equal("cosmosvaloper1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7epjs3u", msg.ValidatorAddress) - require.Len(futureOperations, 0) -} - -// TestSimulateMsgCancelUnbondingDelegation tests the normal scenario of a valid message of type TypeMsgCancelUnbondingDelegation. -// Abonormal scenarios, where the message is -func (s *SimTestSuite) TestSimulateMsgCancelUnbondingDelegation() { - require := s.Require() - blockTime := time.Now().UTC() - ctx := s.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup accounts[1] as validator - validator0 := s.getTestingValidator0(ctx) - - // setup delegation - delTokens := s.stakingKeeper.TokensFromConsensusPower(ctx, 2) - validator0, issuedShares := validator0.AddTokensFromDel(delTokens) - delegator := s.accounts[2] - delegation := types.NewDelegation(delegator.Address.String(), validator0.GetOperator(), issuedShares) - require.NoError(s.stakingKeeper.SetDelegation(ctx, delegation)) - val0bz, err := s.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator0.GetOperator()) - s.Require().NoError(err) - s.Require().NoError(s.distrKeeper.DelegatorStartingInfo.Set(ctx, collections.Join(sdk.ValAddress(val0bz), delegator.Address), distrtypes.NewDelegatorStartingInfo(2, math.LegacyOneDec(), 200))) - - s.setupValidatorRewards(ctx, val0bz) - - // unbonding delegation - udb := types.NewUnbondingDelegation(delegator.Address, val0bz, s.app.LastBlockHeight()+1, blockTime.Add(2*time.Minute), delTokens, 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) - require.NoError(s.stakingKeeper.SetUnbondingDelegation(ctx, udb)) - s.setupValidatorRewards(ctx, val0bz) - - _, err = s.app.FinalizeBlock(&abci.FinalizeBlockRequest{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash, Time: blockTime}) - require.NoError(err) - // execute operation - op := simulation.SimulateMsgCancelUnbondingDelegate(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper) - accounts := []simtypes.Account{delegator} - operationMsg, futureOperations, err := op(s.r, s.app.BaseApp, ctx, accounts, "") - require.NoError(err) - - var msg types.MsgCancelUnbondingDelegation - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - require.True(operationMsg.OK) - require.Equal(sdk.MsgTypeURL(&types.MsgCancelUnbondingDelegation{}), sdk.MsgTypeURL(&msg)) - require.Equal(delegator.Address.String(), msg.DelegatorAddress) - require.Equal(validator0.GetOperator(), msg.ValidatorAddress) - require.Len(futureOperations, 0) -} - -// TestSimulateMsgEditValidator tests the normal scenario of a valid message of type TypeMsgEditValidator. -// Abonormal scenarios, where the message is created by an errors are not tested here. -func (s *SimTestSuite) TestSimulateMsgEditValidator() { - require := s.Require() - blockTime := time.Now().UTC() - ctx := s.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup accounts[0] as validator - _ = s.getTestingValidator0(ctx) - - _, err := s.app.FinalizeBlock(&abci.FinalizeBlockRequest{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash, Time: blockTime}) - require.NoError(err) - // execute operation - op := simulation.SimulateMsgEditValidator(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper) - operationMsg, futureOperations, err := op(s.r, s.app.BaseApp, ctx, s.accounts, "") - require.NoError(err) - - var msg types.MsgEditValidator - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - require.True(operationMsg.OK) - require.Equal(sdk.MsgTypeURL(&types.MsgEditValidator{}), sdk.MsgTypeURL(&msg)) - require.Equal("cosmosvaloper1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7epjs3u", msg.ValidatorAddress) - require.Len(futureOperations, 0) -} - -// TestSimulateMsgDelegate tests the normal scenario of a valid message of type TypeMsgDelegate. -// Abonormal scenarios, where the message is created by an errors are not tested here. -func (s *SimTestSuite) TestSimulateMsgDelegate() { - require := s.Require() - blockTime := time.Now().UTC() - ctx := s.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // execute operation - op := simulation.SimulateMsgDelegate(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper) - operationMsg, futureOperations, err := op(s.r, s.app.BaseApp, ctx, s.accounts[1:], "") - require.NoError(err) - - var msg types.MsgDelegate - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - require.True(operationMsg.OK) - require.Equal("cosmos1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7u4x9a0", msg.DelegatorAddress) - require.Equal("stake", msg.Amount.Denom) - require.Equal(sdk.MsgTypeURL(&types.MsgDelegate{}), sdk.MsgTypeURL(&msg)) - require.Equal("cosmosvaloper122js6qry7nlgp63gcse8muknspuxur77vj3kkr", msg.ValidatorAddress) - require.Len(futureOperations, 0) -} - -// TestSimulateMsgUndelegate tests the normal scenario of a valid message of type TypeMsgUndelegate. -// Abonormal scenarios, where the message is created by an errors are not tested here. -func (s *SimTestSuite) TestSimulateMsgUndelegate() { - require := s.Require() - blockTime := time.Now().UTC() - ctx := s.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup accounts[1] as validator - validator0 := s.getTestingValidator0(ctx) - - // setup delegation - delTokens := s.stakingKeeper.TokensFromConsensusPower(ctx, 2) - validator0, issuedShares := validator0.AddTokensFromDel(delTokens) - delegator := s.accounts[2] - delegation := types.NewDelegation(delegator.Address.String(), validator0.GetOperator(), issuedShares) - require.NoError(s.stakingKeeper.SetDelegation(ctx, delegation)) - val0bz, err := s.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator0.GetOperator()) - s.Require().NoError(err) - s.Require().NoError(s.distrKeeper.DelegatorStartingInfo.Set(ctx, collections.Join(sdk.ValAddress(val0bz), delegator.Address), distrtypes.NewDelegatorStartingInfo(2, math.LegacyOneDec(), 200))) - - s.setupValidatorRewards(ctx, val0bz) - - _, err = s.app.FinalizeBlock(&abci.FinalizeBlockRequest{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash, Time: blockTime}) - require.NoError(err) - // execute operation - op := simulation.SimulateMsgUndelegate(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper) - operationMsg, futureOperations, err := op(s.r, s.app.BaseApp, ctx, s.accounts, "") - require.NoError(err) - - var msg types.MsgUndelegate - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - require.True(operationMsg.OK) - require.Equal("cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.DelegatorAddress) - require.Equal("1646627814093010272", msg.Amount.Amount.String()) - require.Equal("stake", msg.Amount.Denom) - require.Equal(sdk.MsgTypeURL(&types.MsgUndelegate{}), sdk.MsgTypeURL(&msg)) - require.Equal("cosmosvaloper1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7epjs3u", msg.ValidatorAddress) - require.Len(futureOperations, 0) -} - -// TestSimulateMsgBeginRedelegate tests the normal scenario of a valid message of type TypeMsgBeginRedelegate. -// Abonormal scenarios, where the message is created by an errors, are not tested here. -func (s *SimTestSuite) TestSimulateMsgBeginRedelegate() { - require := s.Require() - blockTime := time.Now().UTC() - ctx := s.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup accounts[1] as validator0 and accounts[2] as validator1 - validator0 := s.getTestingValidator0(ctx) - validator1 := s.getTestingValidator1(ctx) - - delTokens := s.stakingKeeper.TokensFromConsensusPower(ctx, 2) - validator1, issuedShares := validator1.AddTokensFromDel(delTokens) - - // setup accounts[3] as delegator - delegator := s.accounts[3] - delegation := types.NewDelegation(delegator.Address.String(), validator0.GetOperator(), issuedShares) - require.NoError(s.stakingKeeper.SetDelegation(ctx, delegation)) - val0bz, err := s.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator0.GetOperator()) - s.Require().NoError(err) - val1bz, err := s.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator1.GetOperator()) - s.Require().NoError(err) - s.Require().NoError(s.distrKeeper.DelegatorStartingInfo.Set(ctx, collections.Join(sdk.ValAddress(val0bz), delegator.Address), distrtypes.NewDelegatorStartingInfo(2, math.LegacyOneDec(), 200))) - - s.setupValidatorRewards(ctx, val0bz) - s.setupValidatorRewards(ctx, val1bz) - - _, err = s.app.FinalizeBlock(&abci.FinalizeBlockRequest{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash, Time: blockTime}) - require.NoError(err) - - // execute operation - op := simulation.SimulateMsgBeginRedelegate(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper) - operationMsg, futureOperations, err := op(s.r, s.app.BaseApp, ctx, s.accounts, "") - s.T().Logf("operation message: %v", operationMsg) - require.NoError(err) - - var msg types.MsgBeginRedelegate - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - require.True(operationMsg.OK) - require.Equal("cosmos1ua0fwyws7vzjrry3pqkklvf8mny93l9s9zg0h4", msg.DelegatorAddress) - require.Equal("stake", msg.Amount.Denom) - require.Equal(sdk.MsgTypeURL(&types.MsgBeginRedelegate{}), sdk.MsgTypeURL(&msg)) - require.Equal("cosmosvaloper1ghekyjucln7y67ntx7cf27m9dpuxxemnsvnaes", msg.ValidatorDstAddress) - require.Equal("cosmosvaloper1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7epjs3u", msg.ValidatorSrcAddress) - require.Len(futureOperations, 0) -} - -func (s *SimTestSuite) TestSimulateRotateConsPubKey() { - require := s.Require() - blockTime := time.Now().UTC() - ctx := s.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - _ = s.getTestingValidator2(ctx) - - // begin a new block - _, err := s.app.FinalizeBlock(&abci.FinalizeBlockRequest{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash, Time: blockTime}) - require.NoError(err) - - // execute operation - op := simulation.SimulateMsgRotateConsPubKey(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper) - operationMsg, futureOperations, err := op(s.r, s.app.BaseApp, ctx, s.accounts, "") - require.NoError(err) - - var msg types.MsgRotateConsPubKey - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - - require.True(operationMsg.OK) - require.Equal(sdk.MsgTypeURL(&types.MsgRotateConsPubKey{}), sdk.MsgTypeURL(&msg)) - require.Equal("cosmosvaloper1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7epjs3u", msg.ValidatorAddress) - require.Len(futureOperations, 0) -} - -func (s *SimTestSuite) getTestingValidator0(ctx sdk.Context) types.Validator { - commission0 := types.NewCommission(math.LegacyZeroDec(), math.LegacyOneDec(), math.LegacyOneDec()) - return s.getTestingValidator(ctx, commission0, 1) -} - -func (s *SimTestSuite) getTestingValidator1(ctx sdk.Context) types.Validator { - commission1 := types.NewCommission(math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec()) - return s.getTestingValidator(ctx, commission1, 2) -} - -func (s *SimTestSuite) getTestingValidator(ctx sdk.Context, commission types.Commission, n int) types.Validator { - account := s.accounts[n] - valPubKey := account.PubKey - valAddr := sdk.ValAddress(account.PubKey.Address().Bytes()) - validator := testutil.NewValidator(s.T(), valAddr, valPubKey) - validator, err := validator.SetInitialCommission(commission) - s.Require().NoError(err) - - validator.DelegatorShares = math.LegacyNewDec(100) - validator.Tokens = s.stakingKeeper.TokensFromConsensusPower(ctx, 100) - - s.Require().NoError(s.stakingKeeper.SetValidator(ctx, validator)) - - return validator -} - -func (s *SimTestSuite) getTestingValidator2(ctx sdk.Context) types.Validator { - val := s.getTestingValidator0(ctx) - val.Status = types.Bonded - s.Require().NoError(s.stakingKeeper.SetValidator(ctx, val)) - s.Require().NoError(s.stakingKeeper.SetValidatorByConsAddr(ctx, val)) - return val -} - -func (s *SimTestSuite) setupValidatorRewards(ctx sdk.Context, valAddress sdk.ValAddress) { - decCoins := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, math.LegacyOneDec())} - historicalRewards := distrtypes.NewValidatorHistoricalRewards(decCoins, 2) - s.Require().NoError(s.distrKeeper.ValidatorHistoricalRewards.Set(ctx, collections.Join(valAddress, uint64(2)), historicalRewards)) - // setup current revards - currentRewards := distrtypes.NewValidatorCurrentRewards(decCoins, 3) - s.Require().NoError(s.distrKeeper.ValidatorCurrentRewards.Set(ctx, valAddress, currentRewards)) -} - -func TestSimTestSuite(t *testing.T) { - suite.Run(t, new(SimTestSuite)) -} diff --git a/tests/sims/authz/operations_test.go b/tests/sims/authz/operations_test.go deleted file mode 100644 index 3769d30c798b..000000000000 --- a/tests/sims/authz/operations_test.go +++ /dev/null @@ -1,224 +0,0 @@ -package authz - -import ( - "math/rand" - "testing" - "time" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/core/header" - coretesting "cosmossdk.io/core/testing" - "cosmossdk.io/depinject" - _ "cosmossdk.io/x/accounts" // import as blank for app wiring - "cosmossdk.io/x/authz" - authzkeeper "cosmossdk.io/x/authz/keeper" - _ "cosmossdk.io/x/authz/module" // import as blank for app wiring - "cosmossdk.io/x/authz/simulation" - _ "cosmossdk.io/x/bank" // import as blank for app wiring - bankkeeper "cosmossdk.io/x/bank/keeper" - banktestutil "cosmossdk.io/x/bank/testutil" - banktypes "cosmossdk.io/x/bank/types" - _ "cosmossdk.io/x/consensus" // import as blank for app wiring - _ "cosmossdk.io/x/gov" // import as blank for app wiring - _ "cosmossdk.io/x/mint" // import as blank for app wiring - _ "cosmossdk.io/x/staking" // import as blank for app wiring - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/testutil/configurator" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - _ "github.com/cosmos/cosmos-sdk/x/auth" // import as blank for app wiring - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/genutil" // import as blank for app wiring -) - -var AppConfig = configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.BankModule(), - configurator.StakingModule(), - configurator.TxModule(), - configurator.ConsensusModule(), - configurator.GenutilModule(), - configurator.AuthzModule(), - configurator.MintModule(), -) - -type SimTestSuite struct { - suite.Suite - - ctx sdk.Context - - app *runtime.App - codec codec.Codec - interfaceRegistry codectypes.InterfaceRegistry - txConfig client.TxConfig - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.Keeper - authzKeeper authzkeeper.Keeper -} - -func (suite *SimTestSuite) SetupTest() { - app, err := simtestutil.Setup( - depinject.Configs( - AppConfig, - depinject.Supply(coretesting.NewNopLogger()), - ), - &suite.codec, - &suite.interfaceRegistry, - &suite.txConfig, - &suite.accountKeeper, - &suite.bankKeeper, - &suite.authzKeeper, - ) - suite.Require().NoError(err) - suite.app = app - suite.ctx = app.BaseApp.NewContext(false) -} - -func (suite *SimTestSuite) TestWeightedOperations() { - cdc := suite.codec - appParams := make(simtypes.AppParams) - - weightedOps := simulation.WeightedOperations(suite.interfaceRegistry, appParams, cdc, suite.txConfig, suite.accountKeeper, - suite.bankKeeper, suite.authzKeeper) - - s := rand.NewSource(3) - r := rand.New(s) - // setup 2 accounts - accs := suite.getTestingAccounts(r, 2) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {simulation.WeightGrant, authz.ModuleName, simulation.TypeMsgGrant}, - {simulation.WeightExec, authz.ModuleName, simulation.TypeMsgExec}, - {simulation.WeightRevoke, authz.ModuleName, simulation.TypeMsgRevoke}, - } - - require := suite.Require() - for i, w := range weightedOps { - op, _, err := w.Op()(r, suite.app.BaseApp, suite.ctx, accs, "") - require.NoError(err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - require.Equal(expected[i].weight, w.Weight(), "weight should be the same. %v", op.Comment) - require.Equal(expected[i].opMsgRoute, op.Route, "route should be the same. %v", op.Comment) - require.Equal(expected[i].opMsgName, op.Name, "operation Msg name should be the same %v", op.Comment) - } -} - -func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { - accounts := simtypes.RandomAccounts(r, n) - - initAmt := sdk.TokensFromConsensusPower(200000, sdk.DefaultPowerReduction) - initCoins := sdk.NewCoins(sdk.NewCoin("stake", initAmt)) - - // add coins to the accounts - for _, account := range accounts { - acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, account.Address) - suite.accountKeeper.SetAccount(suite.ctx, acc) - suite.Require().NoError(banktestutil.FundAccount(suite.ctx, suite.bankKeeper, account.Address, initCoins)) - } - - return accounts -} - -func (suite *SimTestSuite) TestSimulateGrant() { - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - blockTime := time.Now().UTC() - ctx := suite.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - granter := accounts[0] - grantee := accounts[1] - - // execute operation - op := simulation.SimulateMsgGrant(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.authzKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, ctx, accounts, "") - suite.Require().NoError(err) - - var msg authz.MsgGrant - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(granter.Address.String(), msg.Granter) - suite.Require().Equal(grantee.Address.String(), msg.Grantee) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateRevoke() { - // setup 3 accounts - s := rand.NewSource(2) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - initAmt := sdk.TokensFromConsensusPower(200000, sdk.DefaultPowerReduction) - initCoins := sdk.NewCoins(sdk.NewCoin("stake", initAmt)) - - granter := accounts[0] - grantee := accounts[1] - a := banktypes.NewSendAuthorization(initCoins, nil, suite.accountKeeper.AddressCodec()) - expire := time.Now().Add(30 * time.Hour) - - err := suite.authzKeeper.SaveGrant(suite.ctx, grantee.Address, granter.Address, a, &expire) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgRevoke(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.authzKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg authz.MsgRevoke - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(granter.Address.String(), msg.Granter) - suite.Require().Equal(grantee.Address.String(), msg.Grantee) - suite.Require().Equal(banktypes.SendAuthorization{}.MsgTypeURL(), msg.MsgTypeUrl) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateExec() { - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - initAmt := sdk.TokensFromConsensusPower(200000, sdk.DefaultPowerReduction) - initCoins := sdk.NewCoins(sdk.NewCoin("stake", initAmt)) - - granter := accounts[0] - grantee := accounts[1] - a := banktypes.NewSendAuthorization(initCoins, nil, suite.accountKeeper.AddressCodec()) - expire := suite.ctx.HeaderInfo().Time.Add(1 * time.Hour) - - err := suite.authzKeeper.SaveGrant(suite.ctx, grantee.Address, granter.Address, a, &expire) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgExec(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.authzKeeper, suite.codec) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg authz.MsgExec - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(grantee.Address.String(), msg.Grantee) - suite.Require().Len(futureOperations, 0) -} - -func TestSimTestSuite(t *testing.T) { - suite.Run(t, new(SimTestSuite)) -} diff --git a/tests/sims/bank/operations_test.go b/tests/sims/bank/operations_test.go deleted file mode 100644 index e2177fb14a20..000000000000 --- a/tests/sims/bank/operations_test.go +++ /dev/null @@ -1,217 +0,0 @@ -package simulation_test - -import ( - "math/rand" - "testing" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/depinject" - "cosmossdk.io/log" - _ "cosmossdk.io/x/accounts" - _ "cosmossdk.io/x/bank" - "cosmossdk.io/x/bank/keeper" - "cosmossdk.io/x/bank/simulation" - "cosmossdk.io/x/bank/testutil" - "cosmossdk.io/x/bank/types" - _ "cosmossdk.io/x/consensus" - _ "cosmossdk.io/x/staking" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/testutil/configurator" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - _ "github.com/cosmos/cosmos-sdk/x/auth" - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" -) - -type SimTestSuite struct { - suite.Suite - - ctx sdk.Context - accountKeeper types.AccountKeeper - bankKeeper keeper.Keeper - cdc codec.Codec - txConfig client.TxConfig - app *runtime.App -} - -func (suite *SimTestSuite) SetupTest() { - var ( - appBuilder *runtime.AppBuilder - err error - ) - suite.app, err = simtestutil.Setup( - depinject.Configs( - configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.BankModule(), - configurator.StakingModule(), - configurator.ConsensusModule(), - configurator.TxModule(), - ), - depinject.Supply(log.NewNopLogger()), - ), &suite.accountKeeper, &suite.bankKeeper, &suite.cdc, &suite.txConfig, &appBuilder) - - suite.NoError(err) - - suite.ctx = suite.app.BaseApp.NewContext(false) -} - -// TestWeightedOperations tests the weights of the operations. -func (suite *SimTestSuite) TestWeightedOperations() { - cdc := suite.cdc - appParams := make(simtypes.AppParams) - - weightesOps := simulation.WeightedOperations(appParams, cdc, suite.txConfig, suite.accountKeeper, suite.bankKeeper) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accs := suite.getTestingAccounts(r, 3) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {100, types.ModuleName, sdk.MsgTypeURL(&types.MsgSend{})}, - {10, types.ModuleName, sdk.MsgTypeURL(&types.MsgMultiSend{})}, - } - - for i, w := range weightesOps { - operationMsg, _, err := w.Op()(r, suite.app.BaseApp, suite.ctx, accs, "") - suite.Require().NoError(err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - suite.Require().Equal(expected[i].weight, w.Weight(), "weight should be the same") - suite.Require().Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - suite.Require().Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -// TestSimulateMsgSend tests the normal scenario of a valid message of type TypeMsgSend. -// Abonormal scenarios, where the message is created by an errors, are not tested here. -func (suite *SimTestSuite) TestSimulateMsgSend() { - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - - // execute operation - op := simulation.SimulateMsgSend(suite.txConfig, suite.accountKeeper, suite.bankKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg types.MsgSend - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal("65337742stake", msg.Amount.String()) - suite.Require().Equal("cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.FromAddress) - suite.Require().Equal("cosmos1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7u4x9a0", msg.ToAddress) - suite.Require().Equal(sdk.MsgTypeURL(&types.MsgSend{}), sdk.MsgTypeURL(&msg)) - suite.Require().Len(futureOperations, 0) -} - -// TestSimulateMsgMultiSend tests the normal scenario of a valid message of type TypeMsgMultiSend. -// Abonormal scenarios, where the message is created by an errors, are not tested here. -func (suite *SimTestSuite) TestSimulateMsgMultiSend() { - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - - // execute operation - op := simulation.SimulateMsgMultiSend(suite.txConfig, suite.accountKeeper, suite.bankKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - require := suite.Require() - require.NoError(err) - - var msg types.MsgMultiSend - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - require.True(operationMsg.OK) - require.Len(msg.Inputs, 1) - require.Equal("cosmos1tnh2q55v8wyygtt9srz5safamzdengsnqeycj3", msg.Inputs[0].Address) - require.Equal("114949958stake", msg.Inputs[0].Coins.String()) - require.Len(msg.Outputs, 2) - require.Equal("cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Outputs[1].Address) - require.Equal("107287087stake", msg.Outputs[1].Coins.String()) - suite.Require().Equal(sdk.MsgTypeURL(&types.MsgMultiSend{}), sdk.MsgTypeURL(&msg)) - require.Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateModuleAccountMsgSend() { - const moduleAccount = 1 - - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 1) - - // execute operation - op := simulation.SimulateMsgSendToModuleAccount(suite.txConfig, suite.accountKeeper, suite.bankKeeper, moduleAccount) - - s = rand.NewSource(1) - r = rand.New(s) - - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().Error(err) - - var msg types.MsgSend - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().False(operationMsg.OK) - suite.Require().Equal(operationMsg.Comment, "invalid transfers") - suite.Require().Equal(sdk.MsgTypeURL(&types.MsgSend{}), sdk.MsgTypeURL(&msg)) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateMsgMultiSendToModuleAccount() { - const mAccount = 2 - - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - - // execute operation - op := simulation.SimulateMsgMultiSendToModuleAccount(suite.txConfig, suite.accountKeeper, suite.bankKeeper, mAccount) - - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().Error(err) - - var msg types.MsgMultiSend - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().False(operationMsg.OK) // sending tokens to a module account should fail - suite.Require().Equal(operationMsg.Comment, "invalid transfers") - suite.Require().Equal(sdk.MsgTypeURL(&types.MsgMultiSend{}), sdk.MsgTypeURL(&msg)) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { - accounts := simtypes.RandomAccounts(r, n) - - initAmt := sdk.TokensFromConsensusPower(200, sdk.DefaultPowerReduction) - initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) - - // add coins to the accounts - for _, account := range accounts { - acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, account.Address) - suite.accountKeeper.SetAccount(suite.ctx, acc) - suite.Require().NoError(testutil.FundAccount(suite.ctx, suite.bankKeeper, account.Address, initCoins)) - } - - return accounts -} - -func TestSimTestSuite(t *testing.T) { - suite.Run(t, new(SimTestSuite)) -} diff --git a/tests/sims/distribution/app_config.go b/tests/sims/distribution/app_config.go deleted file mode 100644 index 989d74b74f5a..000000000000 --- a/tests/sims/distribution/app_config.go +++ /dev/null @@ -1,29 +0,0 @@ -package distribution - -import ( - _ "cosmossdk.io/x/accounts" // import as blank for app wiring - _ "cosmossdk.io/x/bank" // import as blank for app wiring - _ "cosmossdk.io/x/consensus" // import as blank for app wiring - _ "cosmossdk.io/x/distribution" // import as blank for app wiring - _ "cosmossdk.io/x/mint" // import as blank for app wiring - _ "cosmossdk.io/x/protocolpool" // import as blank for app wiring - _ "cosmossdk.io/x/staking" // import as blank for app wiring - - "github.com/cosmos/cosmos-sdk/testutil/configurator" - _ "github.com/cosmos/cosmos-sdk/x/auth" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/genutil" // import as blank for app wiring -) - -var AppConfig = configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.BankModule(), - configurator.StakingModule(), - configurator.TxModule(), - configurator.ConsensusModule(), - configurator.GenutilModule(), - configurator.DistributionModule(), - configurator.MintModule(), - configurator.ProtocolPoolModule(), -) diff --git a/tests/sims/distribution/operations_test.go b/tests/sims/distribution/operations_test.go deleted file mode 100644 index 972217c6cf37..000000000000 --- a/tests/sims/distribution/operations_test.go +++ /dev/null @@ -1,287 +0,0 @@ -package distribution - -import ( - "math/rand" - "testing" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/collections" - "cosmossdk.io/depinject" - "cosmossdk.io/log" - "cosmossdk.io/math" - bankkeeper "cosmossdk.io/x/bank/keeper" - banktestutil "cosmossdk.io/x/bank/testutil" - "cosmossdk.io/x/distribution/keeper" - "cosmossdk.io/x/distribution/simulation" - "cosmossdk.io/x/distribution/types" - stakingkeeper "cosmossdk.io/x/staking/keeper" - stakingtypes "cosmossdk.io/x/staking/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/codec/address" - "github.com/cosmos/cosmos-sdk/runtime" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" -) - -// TestWeightedOperations tests the weights of the operations. -func (suite *SimTestSuite) TestWeightedOperations() { - appParams := make(simtypes.AppParams) - - weightedOps := simulation.WeightedOperations(appParams, suite.cdc, suite.txConfig, suite.accountKeeper, - suite.bankKeeper, suite.distrKeeper, suite.stakingKeeper) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accs := suite.getTestingAccounts(r, 3) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {simulation.DefaultWeightMsgSetWithdrawAddress, types.ModuleName, sdk.MsgTypeURL(&types.MsgSetWithdrawAddress{})}, - {simulation.DefaultWeightMsgWithdrawDelegationReward, types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{})}, - {simulation.DefaultWeightMsgWithdrawValidatorCommission, types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawValidatorCommission{})}, - } - - for i, w := range weightedOps { - operationMsg, _, err := w.Op()(r, suite.app.BaseApp, suite.ctx, accs, "") - suite.Require().NoError(err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - suite.Require().Equal(expected[i].weight, w.Weight(), "weight should be the same") - suite.Require().Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - suite.Require().Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -// TestSimulateMsgSetWithdrawAddress tests the normal scenario of a valid message of type TypeMsgSetWithdrawAddress. -// Abonormal scenarios, where the message is created by an errors, are not tested here. -func (suite *SimTestSuite) TestSimulateMsgSetWithdrawAddress() { - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - - // execute operation - op := simulation.SimulateMsgSetWithdrawAddress(suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.distrKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg types.MsgSetWithdrawAddress - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal("cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.DelegatorAddress) - suite.Require().Equal("cosmos1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7u4x9a0", msg.WithdrawAddress) - suite.Require().Equal(sdk.MsgTypeURL(&types.MsgSetWithdrawAddress{}), sdk.MsgTypeURL(&msg)) - suite.Require().Len(futureOperations, 0) -} - -// TestSimulateMsgWithdrawDelegatorReward tests the normal scenario of a valid message -// of type TypeMsgWithdrawDelegatorReward. -// Abonormal scenarios, where the message is created by an errors, are not tested here. -func (suite *SimTestSuite) TestSimulateMsgWithdrawDelegatorReward() { - // setup 3 accounts - s := rand.NewSource(4) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - - // setup accounts[0] as validator - validator0 := suite.getTestingValidator0(accounts) - - // setup delegation - delTokens := sdk.TokensFromConsensusPower(2, sdk.DefaultPowerReduction) - validator0, issuedShares := validator0.AddTokensFromDel(delTokens) - delegator := accounts[1] - delegation := stakingtypes.NewDelegation(delegator.Address.String(), validator0.GetOperator(), issuedShares) - suite.Require().NoError(suite.stakingKeeper.SetDelegation(suite.ctx, delegation)) - valBz, err := address.NewBech32Codec("cosmosvaloper").StringToBytes(validator0.GetOperator()) - suite.Require().NoError(err) - - suite.Require().NoError(suite.distrKeeper.DelegatorStartingInfo.Set(suite.ctx, collections.Join(sdk.ValAddress(valBz), delegator.Address), types.NewDelegatorStartingInfo(2, math.LegacyOneDec(), 200))) - - suite.setupValidatorRewards(valBz) - - // execute operation - op := simulation.SimulateMsgWithdrawDelegatorReward(suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.distrKeeper, suite.stakingKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg types.MsgWithdrawDelegatorReward - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal("cosmosvaloper1l4s054098kk9hmr5753c6k3m2kw65h686d3mhr", msg.ValidatorAddress) - suite.Require().Equal("cosmos1d6u7zhjwmsucs678d7qn95uqajd4ucl9jcjt26", msg.DelegatorAddress) - suite.Require().Equal(sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), sdk.MsgTypeURL(&msg)) - suite.Require().Len(futureOperations, 0) -} - -// TestSimulateMsgWithdrawValidatorCommission tests the normal scenario of a valid message -// of type TypeMsgWithdrawValidatorCommission. -// Abonormal scenarios, where the message is created by an errors, are not tested here. -func (suite *SimTestSuite) TestSimulateMsgWithdrawValidatorCommission() { - suite.testSimulateMsgWithdrawValidatorCommission("atoken") - suite.testSimulateMsgWithdrawValidatorCommission("tokenxxx") -} - -// all the checks in this function should not fail if we change the tokenName -func (suite *SimTestSuite) testSimulateMsgWithdrawValidatorCommission(tokenName string) { - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - - // setup accounts[0] as validator - validator0 := suite.getTestingValidator0(accounts) - - // set module account coins - distrAcc := suite.distrKeeper.GetDistributionAccount(suite.ctx) - suite.Require().NoError(banktestutil.FundModuleAccount(suite.ctx, suite.bankKeeper, distrAcc.GetName(), sdk.NewCoins( - sdk.NewCoin(tokenName, math.NewInt(10)), - sdk.NewCoin("stake", math.NewInt(5)), - ))) - suite.accountKeeper.SetModuleAccount(suite.ctx, distrAcc) - - // set outstanding rewards - valCommission := sdk.NewDecCoins( - sdk.NewDecCoinFromDec(tokenName, math.LegacyNewDec(5).Quo(math.LegacyNewDec(2))), - sdk.NewDecCoinFromDec("stake", math.LegacyNewDec(1).Quo(math.LegacyNewDec(1))), - ) - valCodec := address.NewBech32Codec("cosmosvaloper") - - val0, err := valCodec.StringToBytes(validator0.GetOperator()) - suite.Require().NoError(err) - - genVal0, err := valCodec.StringToBytes(suite.genesisVals[0].GetOperator()) - suite.Require().NoError(err) - - suite.Require().NoError(suite.distrKeeper.ValidatorOutstandingRewards.Set(suite.ctx, val0, types.ValidatorOutstandingRewards{Rewards: valCommission})) - suite.Require().NoError(suite.distrKeeper.ValidatorOutstandingRewards.Set(suite.ctx, genVal0, types.ValidatorOutstandingRewards{Rewards: valCommission})) - - // setup validator accumulated commission - suite.Require().NoError(suite.distrKeeper.ValidatorsAccumulatedCommission.Set(suite.ctx, val0, types.ValidatorAccumulatedCommission{Commission: valCommission})) - suite.Require().NoError(suite.distrKeeper.ValidatorsAccumulatedCommission.Set(suite.ctx, genVal0, types.ValidatorAccumulatedCommission{Commission: valCommission})) - - // execute operation - op := simulation.SimulateMsgWithdrawValidatorCommission(suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.distrKeeper, suite.stakingKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - if !operationMsg.OK { - suite.Require().Equal("could not find account", operationMsg.Comment) - } else { - suite.Require().NoError(err) - - var msg types.MsgWithdrawValidatorCommission - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal("cosmosvaloper1tnh2q55v8wyygtt9srz5safamzdengsn9dsd7z", msg.ValidatorAddress) - suite.Require().Equal(sdk.MsgTypeURL(&types.MsgWithdrawValidatorCommission{}), sdk.MsgTypeURL(&msg)) - suite.Require().Len(futureOperations, 0) - } -} - -type SimTestSuite struct { - suite.Suite - - ctx sdk.Context - app *runtime.App - genesisVals []stakingtypes.Validator - - txConfig client.TxConfig - cdc codec.Codec - stakingKeeper *stakingkeeper.Keeper - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.Keeper - distrKeeper keeper.Keeper -} - -func (suite *SimTestSuite) SetupTest() { - var ( - appBuilder *runtime.AppBuilder - err error - ) - suite.app, err = simtestutil.Setup( - depinject.Configs( - AppConfig, - depinject.Supply(log.NewNopLogger()), - ), - &suite.accountKeeper, - &suite.bankKeeper, - &suite.cdc, - &appBuilder, - &suite.stakingKeeper, - &suite.distrKeeper, - &suite.txConfig, - ) - - suite.NoError(err) - - suite.ctx = suite.app.BaseApp.NewContext(false) - - genesisVals, err := suite.stakingKeeper.GetAllValidators(suite.ctx) - suite.Require().NoError(err) - suite.Require().Len(genesisVals, 1) - suite.genesisVals = genesisVals -} - -func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { - accounts := simtypes.RandomAccounts(r, n) - - initAmt := suite.stakingKeeper.TokensFromConsensusPower(suite.ctx, 200) - initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) - - // add coins to the accounts - for _, account := range accounts { - acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, account.Address) - suite.accountKeeper.SetAccount(suite.ctx, acc) - suite.Require().NoError(banktestutil.FundAccount(suite.ctx, suite.bankKeeper, account.Address, initCoins)) - } - - return accounts -} - -func (suite *SimTestSuite) getTestingValidator0(accounts []simtypes.Account) stakingtypes.Validator { - commission0 := stakingtypes.NewCommission(math.LegacyZeroDec(), math.LegacyOneDec(), math.LegacyOneDec()) - return suite.getTestingValidator(accounts, commission0, 0) -} - -func (suite *SimTestSuite) getTestingValidator(accounts []simtypes.Account, commission stakingtypes.Commission, n int) stakingtypes.Validator { - require := suite.Require() - account := accounts[n] - valPubKey := account.PubKey - valAddr := sdk.ValAddress(account.PubKey.Address().Bytes()) - validator, err := stakingtypes.NewValidator(valAddr.String(), valPubKey, stakingtypes.Description{}) - require.NoError(err) - validator, err = validator.SetInitialCommission(commission) - require.NoError(err) - validator.DelegatorShares = math.LegacyNewDec(100) - validator.Tokens = math.NewInt(1000000) - - suite.Require().NoError(suite.stakingKeeper.SetValidator(suite.ctx, validator)) - - return validator -} - -func (suite *SimTestSuite) setupValidatorRewards(valAddress sdk.ValAddress) { - decCoins := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, math.LegacyOneDec())} - historicalRewards := types.NewValidatorHistoricalRewards(decCoins, 2) - suite.Require().NoError(suite.distrKeeper.ValidatorHistoricalRewards.Set(suite.ctx, collections.Join(valAddress, uint64(2)), historicalRewards)) - // setup current revards - currentRewards := types.NewValidatorCurrentRewards(decCoins, 3) - suite.Require().NoError(suite.distrKeeper.ValidatorCurrentRewards.Set(suite.ctx, valAddress, currentRewards)) -} - -func TestSimTestSuite(t *testing.T) { - suite.Run(t, new(SimTestSuite)) -} diff --git a/tests/sims/feegrant/operations_test.go b/tests/sims/feegrant/operations_test.go deleted file mode 100644 index 11b4f39615c8..000000000000 --- a/tests/sims/feegrant/operations_test.go +++ /dev/null @@ -1,213 +0,0 @@ -package simulation_test - -import ( - "math/rand" - "testing" - "time" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/core/header" - "cosmossdk.io/depinject" - "cosmossdk.io/log" - _ "cosmossdk.io/x/accounts" // import as blank for app wiring - _ "cosmossdk.io/x/bank" - bankkeeper "cosmossdk.io/x/bank/keeper" - banktestutil "cosmossdk.io/x/bank/testutil" - _ "cosmossdk.io/x/consensus" - "cosmossdk.io/x/feegrant" - "cosmossdk.io/x/feegrant/keeper" - _ "cosmossdk.io/x/feegrant/module" - "cosmossdk.io/x/feegrant/simulation" - _ "cosmossdk.io/x/mint" - _ "cosmossdk.io/x/staking" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/testutil/configurator" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - _ "github.com/cosmos/cosmos-sdk/x/auth" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" - _ "github.com/cosmos/cosmos-sdk/x/genutil" -) - -type SimTestSuite struct { - suite.Suite - - app *runtime.App - ctx sdk.Context - feegrantKeeper keeper.Keeper - interfaceRegistry codectypes.InterfaceRegistry - txConfig client.TxConfig - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.Keeper - cdc codec.Codec -} - -func (suite *SimTestSuite) SetupTest() { - var err error - suite.app, err = simtestutil.Setup( - depinject.Configs( - configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.BankModule(), - configurator.StakingModule(), - configurator.TxModule(), - configurator.ConsensusModule(), - configurator.GenutilModule(), - configurator.FeegrantModule(), - ), - depinject.Supply(log.NewNopLogger()), - ), - &suite.feegrantKeeper, - &suite.bankKeeper, - &suite.accountKeeper, - &suite.interfaceRegistry, - &suite.txConfig, - &suite.cdc, - ) - suite.Require().NoError(err) - - suite.ctx = suite.app.BaseApp.NewContext(false).WithHeaderInfo(header.Info{Time: time.Now()}) -} - -func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { - accounts := simtypes.RandomAccounts(r, n) - initAmt := sdk.TokensFromConsensusPower(200, sdk.DefaultPowerReduction) - initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) - - // add coins to the accounts - for _, account := range accounts { - acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, account.Address) - suite.accountKeeper.SetAccount(suite.ctx, acc) - err := banktestutil.FundAccount(suite.ctx, suite.bankKeeper, account.Address, initCoins) - suite.Require().NoError(err) - } - - return accounts -} - -func (suite *SimTestSuite) TestWeightedOperations() { - require := suite.Require() - - appParams := make(simtypes.AppParams) - - weightedOps := simulation.WeightedOperations( - appParams, suite.txConfig, suite.accountKeeper, - suite.bankKeeper, suite.feegrantKeeper, - ) - - s := rand.NewSource(1) - r := rand.New(s) - accs := suite.getTestingAccounts(r, 3) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - { - simulation.DefaultWeightGrantAllowance, - feegrant.ModuleName, - sdk.MsgTypeURL(&feegrant.MsgGrantAllowance{}), - }, - { - simulation.DefaultWeightRevokeAllowance, - feegrant.ModuleName, - sdk.MsgTypeURL(&feegrant.MsgRevokeAllowance{}), - }, - } - - for i, w := range weightedOps { - operationMsg, _, err := w.Op()(r, suite.app.BaseApp, suite.ctx.WithHeaderInfo(header.Info{Time: time.Now()}), accs, suite.ctx.ChainID()) - require.NoError(err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - require.Equal(expected[i].weight, w.Weight(), "weight should be the same") - require.Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - require.Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -func (suite *SimTestSuite) TestSimulateMsgGrantAllowance() { - app, ctx := suite.app, suite.ctx - require := suite.Require() - - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - addr1, err := suite.accountKeeper.AddressCodec().BytesToString(accounts[1].Address) - require.NoError(err) - addr2, err := suite.accountKeeper.AddressCodec().BytesToString(accounts[2].Address) - require.NoError(err) - - // execute operation - op := simulation.SimulateMsgGrantAllowance(suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.feegrantKeeper) - operationMsg, futureOperations, err := op(r, app.BaseApp, ctx.WithHeaderInfo(header.Info{Time: time.Now()}), accounts, "") - require.NoError(err) - - var msg feegrant.MsgGrantAllowance - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - require.True(operationMsg.OK) - require.Equal(addr2, msg.Granter) - require.Equal(addr1, msg.Grantee) - require.Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateMsgRevokeAllowance() { - app, ctx := suite.app, suite.ctx - require := suite.Require() - - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - - feeAmt := sdk.TokensFromConsensusPower(200000, sdk.DefaultPowerReduction) - feeCoins := sdk.NewCoins(sdk.NewCoin("foo", feeAmt)) - - granter, grantee := accounts[0], accounts[1] - - oneYear := ctx.HeaderInfo().Time.AddDate(1, 0, 0) - err := suite.feegrantKeeper.GrantAllowance( - ctx, - granter.Address, - grantee.Address, - &feegrant.BasicAllowance{ - SpendLimit: feeCoins, - Expiration: &oneYear, - }, - ) - require.NoError(err) - - granterStr, err := suite.accountKeeper.AddressCodec().BytesToString(accounts[0].Address) - require.NoError(err) - granteeStr, err := suite.accountKeeper.AddressCodec().BytesToString(accounts[1].Address) - require.NoError(err) - - // execute operation - op := simulation.SimulateMsgRevokeAllowance(suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.feegrantKeeper) - operationMsg, futureOperations, err := op(r, app.BaseApp, ctx, accounts, "") - require.NoError(err) - - var msg feegrant.MsgRevokeAllowance - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - require.True(operationMsg.OK) - require.Equal(granterStr, msg.Granter) - require.Equal(granteeStr, msg.Grantee) - require.Len(futureOperations, 0) -} - -func TestSimTestSuite(t *testing.T) { - suite.Run(t, new(SimTestSuite)) -} diff --git a/tests/sims/gov/operations_test.go b/tests/sims/gov/operations_test.go deleted file mode 100644 index 95f99f33ab19..000000000000 --- a/tests/sims/gov/operations_test.go +++ /dev/null @@ -1,428 +0,0 @@ -package simulation_test - -import ( - "context" - "fmt" - "math/rand" - "testing" - "time" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/require" - - "cosmossdk.io/core/address" - "cosmossdk.io/core/header" - "cosmossdk.io/depinject" - "cosmossdk.io/log" - _ "cosmossdk.io/x/accounts" - _ "cosmossdk.io/x/bank" - bankkeeper "cosmossdk.io/x/bank/keeper" - "cosmossdk.io/x/bank/testutil" - _ "cosmossdk.io/x/consensus" - _ "cosmossdk.io/x/gov" - "cosmossdk.io/x/gov/keeper" - "cosmossdk.io/x/gov/simulation" - "cosmossdk.io/x/gov/types" - v1 "cosmossdk.io/x/gov/types/v1" - "cosmossdk.io/x/gov/types/v1beta1" - _ "cosmossdk.io/x/protocolpool" - _ "cosmossdk.io/x/staking" - stakingkeeper "cosmossdk.io/x/staking/keeper" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/testutil/configurator" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - _ "github.com/cosmos/cosmos-sdk/x/auth" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" -) - -var ( - _ simtypes.WeightedProposalMsg = MockWeightedProposals{} - _ simtypes.WeightedProposalContent = MockWeightedProposals{} //nolint:staticcheck // testing legacy code path -) - -type MockWeightedProposals struct { - n int -} - -func (m MockWeightedProposals) AppParamsKey() string { - return fmt.Sprintf("AppParamsKey-%d", m.n) -} - -func (m MockWeightedProposals) DefaultWeight() int { - return m.n -} - -func (m MockWeightedProposals) MsgSimulatorFn() simtypes.MsgSimulatorFnX { - return func(_ context.Context, r *rand.Rand, _ []simtypes.Account, _ address.Codec) (sdk.Msg, error) { - return nil, nil - } -} - -func (m MockWeightedProposals) ContentSimulatorFn() simtypes.ContentSimulatorFn { //nolint:staticcheck // testing legacy code path - return func(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) simtypes.Content { //nolint:staticcheck // testing legacy code path - return v1beta1.NewTextProposal( - fmt.Sprintf("title-%d: %s", m.n, simtypes.RandStringOfLength(r, 100)), - fmt.Sprintf("description-%d: %s", m.n, simtypes.RandStringOfLength(r, 4000)), - ) - } -} - -func mockWeightedProposalMsg(n int) []simtypes.WeightedProposalMsg { - wpc := make([]simtypes.WeightedProposalMsg, n) - for i := 0; i < n; i++ { - wpc[i] = MockWeightedProposals{i} - } - return wpc -} - -func mockWeightedLegacyProposalContent(n int) []simtypes.WeightedProposalContent { //nolint:staticcheck // testing legacy code path - wpc := make([]simtypes.WeightedProposalContent, n) //nolint:staticcheck // testing legacy code path - for i := 0; i < n; i++ { - wpc[i] = MockWeightedProposals{i} - } - return wpc -} - -// TestWeightedOperations tests the weights of the operations. -func TestWeightedOperations(t *testing.T) { - suite, ctx := createTestSuite(t, false) - app := suite.App - ctx.WithChainID("test-chain") - appParams := make(simtypes.AppParams) - - weightesOps := simulation.WeightedOperations(appParams, suite.TxConfig, suite.AccountKeeper, - suite.BankKeeper, suite.GovKeeper, mockWeightedProposalMsg(3), mockWeightedLegacyProposalContent(1), - ) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accs := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, ctx, 3) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {simulation.DefaultWeightMsgDeposit, types.ModuleName, simulation.TypeMsgDeposit}, - {simulation.DefaultWeightMsgVote, types.ModuleName, simulation.TypeMsgVote}, - {simulation.DefaultWeightMsgVoteWeighted, types.ModuleName, simulation.TypeMsgVoteWeighted}, - {simulation.DefaultWeightMsgCancelProposal, types.ModuleName, simulation.TypeMsgCancelProposal}, - {0, types.ModuleName, simulation.TypeMsgSubmitProposal}, - {1, types.ModuleName, simulation.TypeMsgSubmitProposal}, - {2, types.ModuleName, simulation.TypeMsgSubmitProposal}, - {0, types.ModuleName, simulation.TypeMsgSubmitProposal}, - } - - require.Equal(t, len(weightesOps), len(expected), "number of operations should be the same") - for i, w := range weightesOps { - operationMsg, _, err := w.Op()(r, app.BaseApp, ctx, accs, ctx.ChainID()) - require.NoError(t, err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - require.Equal(t, expected[i].weight, w.Weight(), "weight should be the same") - require.Equal(t, expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - require.Equal(t, expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -// TestSimulateMsgSubmitProposal tests the normal scenario of a valid message of type TypeMsgSubmitProposal. -// Abnormal scenarios, where errors occur, are not tested here. -func TestSimulateMsgSubmitProposal(t *testing.T) { - suite, ctx := createTestSuite(t, false) - app := suite.App - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, ctx, 3) - - // execute operation - op := simulation.SimulateMsgSubmitProposal(suite.TxConfig, suite.AccountKeeper, suite.BankKeeper, suite.GovKeeper, MockWeightedProposals{3}.MsgSimulatorFn()) - operationMsg, _, err := op(r, app.BaseApp, ctx, accounts, "") - require.NoError(t, err) - - var msg v1.MsgSubmitProposal - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(t, err) - require.True(t, operationMsg.OK) - require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Proposer) - require.NotEqual(t, len(msg.InitialDeposit), 0) - require.Equal(t, "47841094stake", msg.InitialDeposit[0].String()) - require.Equal(t, simulation.TypeMsgSubmitProposal, sdk.MsgTypeURL(&msg)) -} - -// TestSimulateMsgSubmitLegacyProposal tests the normal scenario of a valid message of type TypeMsgSubmitProposal. -// Abnormal scenarios, where errors occur, are not tested here. -func TestSimulateMsgSubmitLegacyProposal(t *testing.T) { - suite, ctx := createTestSuite(t, false) - app := suite.App - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, ctx, 3) - - // execute operation - op := simulation.SimulateMsgSubmitLegacyProposal(suite.TxConfig, suite.AccountKeeper, suite.BankKeeper, suite.GovKeeper, MockWeightedProposals{3}.ContentSimulatorFn()) - operationMsg, _, err := op(r, app.BaseApp, ctx, accounts, "") - require.NoError(t, err) - - var msg v1.MsgSubmitProposal - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(t, err) - var msgLegacyContent v1.MsgExecLegacyContent - err = proto.Unmarshal(msg.Messages[0].Value, &msgLegacyContent) - require.NoError(t, err) - var textProposal v1beta1.TextProposal - err = proto.Unmarshal(msgLegacyContent.Content.Value, &textProposal) - require.NoError(t, err) - - require.True(t, operationMsg.OK) - require.Equal(t, "cosmos1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7u4x9a0", msg.Proposer) - require.NotEqual(t, len(msg.InitialDeposit), 0) - require.Equal(t, "25166256stake", msg.InitialDeposit[0].String()) - require.Equal(t, "title-3: ZBSpYuLyYggwexjxusrBqDOTtGTOWeLrQKjLxzIivHSlcxgdXhhuTSkuxKGLwQvuyNhYFmBZHeAerqyNEUzXPFGkqEGqiQWIXnku", - textProposal.GetTitle()) - require.Equal(t, "description-3: NJWzHdBNpAXKJPHWQdrGYcAHSctgVlqwqHoLfHsXUdStwfefwzqLuKEhmMyYLdbZrcPgYqjNHxPexsruwEGStAneKbWkQDDIlCWBLSiAASNhZqNFlPtfqPJoxKsgMdzjWqLWdqKQuJqWPMvwPQWZUtVMOTMYKJbfdlZsjdsomuScvDmbDkgRualsxDvRJuCAmPOXitIbcyWsKGSdrEunFAOdmXnsuyFVgJqEjbklvmwrUlsxjRSfKZxGcpayDdgoFcnVSutxjRgOSFzPwidAjubMncNweqpbxhXGchpZUxuFDOtpnhNUycJICRYqsPhPSCjPTWZFLkstHWJxvdPEAyEIxXgLwbNOjrgzmaujiBABBIXvcXpLrbcEWNNQsbjvgJFgJkflpRohHUutvnaUqoopuKjTDaemDeSdqbnOzcfJpcTuAQtZoiLZOoAIlboFDAeGmSNwkvObPRvRWQgWkGkxwtPauYgdkmypLjbqhlHJIQTntgWjXwZdOyYEdQRRLfMSdnxqppqUofqLbLQDUjwKVKfZJUJQPsWIPwIVaSTrmKskoAhvmZyJgeRpkaTfGgrJzAigcxtfshmiDCFkuiluqtMOkidknnTBtumyJYlIsWLnCQclqdVmikUoMOPdPWwYbJxXyqUVicNxFxyqJTenNblyyKSdlCbiXxUiYUiMwXZASYfvMDPFgxniSjWaZTjHkqlJvtBsXqwPpyVxnJVGFWhfSxgOcduoxkiopJvFjMmFabrGYeVtTXLhxVUEiGwYUvndjFGzDVntUvibiyZhfMQdMhgsiuysLMiePBNXifRLMsSmXPkwlPloUbJveCvUlaalhZHuvdkCnkSHbMbmOnrfEGPwQiACiPlnihiaOdbjPqPiTXaHDoJXjSlZmltGqNHHNrcKdlFSCdmVOuvDcBLdSklyGJmcLTbSFtALdGlPkqqecJrpLCXNPWefoTJNgEJlyMEPneVaxxduAAEqQpHWZodWyRkDAxzyMnFMcjSVqeRXLqsNyNtQBbuRvunZflWSbbvXXdkyLikYqutQhLPONXbvhcQZJPSWnOulqQaXmbfFxAkqfYeseSHOQidHwbcsOaMnSrrmGjjRmEMQNuknupMxJiIeVjmgZvbmjPIQTEhQFULQLBMPrxcFPvBinaOPYWGvYGRKxLZdwamfRQQFngcdSlvwjfaPbURasIsGJVHtcEAxnIIrhSriiXLOlbEBLXFElXJFGxHJczRBIxAuPKtBisjKBwfzZFagdNmjdwIRvwzLkFKWRTDPxJCmpzHUcrPiiXXHnOIlqNVoGSXZewdnCRhuxeYGPVTfrNTQNOxZmxInOazUYNTNDgzsxlgiVEHPKMfbesvPHUqpNkUqbzeuzfdrsuLDpKHMUbBMKczKKWOdYoIXoPYtEjfOnlQLoGnbQUCuERdEFaptwnsHzTJDsuZkKtzMpFaZobynZdzNydEeJJHDYaQcwUxcqvwfWwNUsCiLvkZQiSfzAHftYgAmVsXgtmcYgTqJIawstRYJrZdSxlfRiqTufgEQVambeZZmaAyRQbcmdjVUZZCgqDrSeltJGXPMgZnGDZqISrGDOClxXCxMjmKqEPwKHoOfOeyGmqWqihqjINXLqnyTesZePQRqaWDQNqpLgNrAUKulklmckTijUltQKuWQDwpLmDyxLppPVMwsmBIpOwQttYFMjgJQZLYFPmxWFLIeZihkRNnkzoypBICIxgEuYsVWGIGRbbxqVasYnstWomJnHwmtOhAFSpttRYYzBmyEtZXiCthvKvWszTXDbiJbGXMcrYpKAgvUVFtdKUfvdMfhAryctklUCEdjetjuGNfJjajZtvzdYaqInKtFPPLYmRaXPdQzxdSQfmZDEVHlHGEGNSPRFJuIfKLLfUmnHxHnRjmzQPNlqrXgifUdzAGKVabYqvcDeYoTYgPsBUqehrBhmQUgTvDnsdpuhUoxskDdppTsYMcnDIPSwKIqhXDCIxOuXrywahvVavvHkPuaenjLmEbMgrkrQLHEAwrhHkPRNvonNQKqprqOFVZKAtpRSpvQUxMoXCMZLSSbnLEFsjVfANdQNQVwTmGxqVjVqRuxREAhuaDrFgEZpYKhwWPEKBevBfsOIcaZKyykQafzmGPLRAKDtTcJxJVgiiuUkmyMYuDUNEUhBEdoBLJnamtLmMJQgmLiUELIhLpiEvpOXOvXCPUeldLFqkKOwfacqIaRcnnZvERKRMCKUkMABbDHytQqQblrvoxOZkwzosQfDKGtIdfcXRJNqlBNwOCWoQBcEWyqrMlYZIAXYJmLfnjoJepgSFvrgajaBAIksoyeHqgqbGvpAstMIGmIhRYGGNPRIfOQKsGoKgxtsidhTaAePRCBFqZgPDWCIkqOJezGVkjfYUCZTlInbxBXwUAVRsxHTQtJFnnpmMvXDYCVlEmnZBKhmmxQOIQzxFWpJQkQoSAYzTEiDWEOsVLNrbfzeHFRyeYATakQQWmFDLPbVMCJcWjFGJjfqCoVzlbNNEsqxdSmNPjTjHYOkuEMFLkXYGaoJlraLqayMeCsTjWNRDPBywBJLAPVkGQqTwApVVwYAetlwSbzsdHWsTwSIcctkyKDuRWYDQikRqsKTMJchrliONJeaZIzwPQrNbTwxsGdwuduvibtYndRwpdsvyCktRHFalvUuEKMqXbItfGcNGWsGzubdPMYayOUOINjpcFBeESdwpdlTYmrPsLsVDhpTzoMegKrytNVZkfJRPuDCUXxSlSthOohmsuxmIZUedzxKmowKOdXTMcEtdpHaPWgIsIjrViKrQOCONlSuazmLuCUjLltOGXeNgJKedTVrrVCpWYWHyVrdXpKgNaMJVjbXxnVMSChdWKuZdqpisvrkBJPoURDYxWOtpjzZoOpWzyUuYNhCzRoHsMjmmWDcXzQiHIyjwdhPNwiPqFxeUfMVFQGImhykFgMIlQEoZCaRoqSBXTSWAeDumdbsOGtATwEdZlLfoBKiTvodQBGOEcuATWXfiinSjPmJKcWgQrTVYVrwlyMWhxqNbCMpIQNoSMGTiWfPTCezUjYcdWppnsYJihLQCqbNLRGgqrwHuIvsazapTpoPZIyZyeeSueJuTIhpHMEJfJpScshJubJGfkusuVBgfTWQoywSSliQQSfbvaHKiLnyjdSbpMkdBgXepoSsHnCQaYuHQqZsoEOmJCiuQUpJkmfyfbIShzlZpHFmLCsbknEAkKXKfRTRnuwdBeuOGgFbJLbDksHVapaRayWzwoYBEpmrlAxrUxYMUekKbpjPNfjUCjhbdMAnJmYQVZBQZkFVweHDAlaqJjRqoQPoOMLhyvYCzqEuQsAFoxWrzRnTVjStPadhsESlERnKhpEPsfDxNvxqcOyIulaCkmPdambLHvGhTZzysvqFauEgkFRItPfvisehFmoBhQqmkfbHVsgfHXDPJVyhwPllQpuYLRYvGodxKjkarnSNgsXoKEMlaSKxKdcVgvOkuLcfLFfdtXGTclqfPOfeoVLbqcjcXCUEBgAGplrkgsmIEhWRZLlGPGCwKWRaCKMkBHTAcypUrYjWwCLtOPVygMwMANGoQwFnCqFrUGMCRZUGJKTZIGPyldsifauoMnJPLTcDHmilcmahlqOELaAUYDBuzsVywnDQfwRLGIWozYaOAilMBcObErwgTDNGWnwQMUgFFSKtPDMEoEQCTKVREqrXZSGLqwTMcxHfWotDllNkIJPMbXzjDVjPOOjCFuIvTyhXKLyhUScOXvYthRXpPfKwMhptXaxIxgqBoUqzrWbaoLTVpQoottZyPFfNOoMioXHRuFwMRYUiKvcWPkrayyTLOCFJlAyslDameIuqVAuxErqFPEWIScKpBORIuZqoXlZuTvAjEdlEWDODFRregDTqGNoFBIHxvimmIZwLfFyKUfEWAnNBdtdzDmTPXtpHRGdIbuucfTjOygZsTxPjfweXhSUkMhPjMaxKlMIJMOXcnQfyzeOcbWwNbeH", - textProposal.GetDescription()) - require.Equal(t, simulation.TypeMsgSubmitProposal, sdk.MsgTypeURL(&msg)) -} - -// TestSimulateMsgCancelProposal tests the normal scenario of a valid message of type TypeMsgCancelProposal. -// Abnormal scenarios, where errors occur, are not tested here. -func TestSimulateMsgCancelProposal(t *testing.T) { - suite, ctx := createTestSuite(t, false) - app := suite.App - blockTime := time.Now().UTC() - ctx = ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, ctx, 3) - // setup a proposal - proposer, err := suite.AccountKeeper.AddressCodec().BytesToString(accounts[0].Address) - require.NoError(t, err) - content := v1beta1.NewTextProposal("Test", "description") - contentMsg, err := v1.NewLegacyContent(content, suite.GovKeeper.GetGovernanceAccount(ctx).GetAddress().String()) - require.NoError(t, err) - - submitTime := ctx.HeaderInfo().Time - params, _ := suite.GovKeeper.Params.Get(ctx) - depositPeriod := params.MaxDepositPeriod - - proposal, err := v1.NewProposal([]sdk.Msg{contentMsg}, 1, submitTime, submitTime.Add(*depositPeriod), "", "title", "summary", proposer, v1.ProposalType_PROPOSAL_TYPE_STANDARD) - require.NoError(t, err) - - err = suite.GovKeeper.Proposals.Set(ctx, proposal.Id, proposal) - require.NoError(t, err) - - // execute operation - op := simulation.SimulateMsgCancelProposal(suite.TxConfig, suite.AccountKeeper, suite.BankKeeper, suite.GovKeeper) - operationMsg, _, err := op(r, app.BaseApp, ctx, accounts, "") - require.NoError(t, err) - - var msg v1.MsgCancelProposal - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(t, err) - require.NoError(t, err) - require.True(t, operationMsg.OK) - require.Equal(t, uint64(1), msg.ProposalId) - require.Equal(t, proposer, msg.Proposer) - require.Equal(t, simulation.TypeMsgCancelProposal, sdk.MsgTypeURL(&msg)) -} - -// TestSimulateMsgDeposit tests the normal scenario of a valid message of type TypeMsgDeposit. -// Abnormal scenarios, where errors occur, are not tested here. -func TestSimulateMsgDeposit(t *testing.T) { - suite, ctx := createTestSuite(t, false) - app := suite.App - blockTime := time.Now().UTC() - ctx = ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, ctx, 3) - - // setup a proposal - content := v1beta1.NewTextProposal("Test", "description") - contentMsg, err := v1.NewLegacyContent(content, suite.GovKeeper.GetGovernanceAccount(ctx).GetAddress().String()) - require.NoError(t, err) - - submitTime := ctx.HeaderInfo().Time - params, _ := suite.GovKeeper.Params.Get(ctx) - depositPeriod := params.MaxDepositPeriod - - proposal, err := v1.NewProposal([]sdk.Msg{contentMsg}, 1, submitTime, submitTime.Add(*depositPeriod), "", "text proposal", "description", "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", v1.ProposalType_PROPOSAL_TYPE_STANDARD) - require.NoError(t, err) - - err = suite.GovKeeper.Proposals.Set(ctx, proposal.Id, proposal) - require.NoError(t, err) - - // execute operation - op := simulation.SimulateMsgDeposit(suite.TxConfig, suite.AccountKeeper, suite.BankKeeper, suite.GovKeeper, simulation.NewSharedState()) - operationMsg, _, err := op(r, app.BaseApp, ctx, accounts, "") - require.NoError(t, err) - - var msg v1.MsgDeposit - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(t, err) - require.True(t, operationMsg.OK) - require.Equal(t, uint64(1), msg.ProposalId) - require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Depositor) - require.NotEqual(t, len(msg.Amount), 0) - require.Equal(t, "560969stake", msg.Amount[0].String()) - require.Equal(t, simulation.TypeMsgDeposit, sdk.MsgTypeURL(&msg)) -} - -// TestSimulateMsgVote tests the normal scenario of a valid message of type TypeMsgVote. -// Abnormal scenarios, where errors occur, are not tested here. -func TestSimulateMsgVote(t *testing.T) { - suite, ctx := createTestSuite(t, false) - app := suite.App - blockTime := time.Now().UTC() - ctx = ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, ctx, 3) - - // setup a proposal - govAcc := suite.GovKeeper.GetGovernanceAccount(ctx).GetAddress().String() - contentMsg, err := v1.NewLegacyContent(v1beta1.NewTextProposal("Test", "description"), govAcc) - require.NoError(t, err) - - submitTime := ctx.HeaderInfo().Time - params, _ := suite.GovKeeper.Params.Get(ctx) - depositPeriod := params.MaxDepositPeriod - - proposal, err := v1.NewProposal([]sdk.Msg{contentMsg}, 1, submitTime, submitTime.Add(*depositPeriod), "", "text proposal", "description", "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", v1.ProposalType_PROPOSAL_TYPE_STANDARD) - require.NoError(t, err) - - err = suite.GovKeeper.ActivateVotingPeriod(ctx, proposal) - require.NoError(t, err) - - // execute operation - op := simulation.SimulateMsgVote(suite.TxConfig, suite.AccountKeeper, suite.BankKeeper, suite.GovKeeper, simulation.NewSharedState()) - operationMsg, _, err := op(r, app.BaseApp, ctx, accounts, "") - require.NoError(t, err) - - var msg v1.MsgVote - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(t, err) - require.True(t, operationMsg.OK) - require.Equal(t, uint64(1), msg.ProposalId) - require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Voter) - require.Equal(t, v1.OptionYes, msg.Option) - require.Equal(t, simulation.TypeMsgVote, sdk.MsgTypeURL(&msg)) -} - -// TestSimulateMsgVoteWeighted tests the normal scenario of a valid message of type TypeMsgVoteWeighted. -// Abnormal scenarios, where errors occur, are not tested here. -func TestSimulateMsgVoteWeighted(t *testing.T) { - suite, ctx := createTestSuite(t, false) - app := suite.App - blockTime := time.Now().UTC() - ctx = ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, ctx, 3) - - // setup a proposal - govAcc := suite.GovKeeper.GetGovernanceAccount(ctx).GetAddress().String() - contentMsg, err := v1.NewLegacyContent(v1beta1.NewTextProposal("Test", "description"), govAcc) - require.NoError(t, err) - submitTime := ctx.HeaderInfo().Time - params, _ := suite.GovKeeper.Params.Get(ctx) - depositPeriod := params.MaxDepositPeriod - - proposal, err := v1.NewProposal([]sdk.Msg{contentMsg}, 1, submitTime, submitTime.Add(*depositPeriod), "", "text proposal", "test", "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", v1.ProposalType_PROPOSAL_TYPE_STANDARD) - require.NoError(t, err) - - err = suite.GovKeeper.ActivateVotingPeriod(ctx, proposal) - require.NoError(t, err) - - // execute operation - op := simulation.SimulateMsgVoteWeighted(suite.TxConfig, suite.AccountKeeper, suite.BankKeeper, suite.GovKeeper, simulation.NewSharedState()) - operationMsg, _, err := op(r, app.BaseApp, ctx, accounts, "") - require.NoError(t, err) - - var msg v1.MsgVoteWeighted - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(t, err) - require.True(t, operationMsg.OK) - require.Equal(t, uint64(1), msg.ProposalId) - require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Voter) - require.True(t, len(msg.Options) >= 1) - require.Equal(t, simulation.TypeMsgVoteWeighted, sdk.MsgTypeURL(&msg)) -} - -type suite struct { - TxConfig client.TxConfig - AccountKeeper authkeeper.AccountKeeper - BankKeeper bankkeeper.Keeper - GovKeeper *keeper.Keeper - StakingKeeper *stakingkeeper.Keeper - App *runtime.App -} - -// returns context and an app with updated mint keeper -func createTestSuite(t *testing.T, isCheckTx bool) (suite, sdk.Context) { - t.Helper() - res := suite{} - - app, err := simtestutil.Setup( - depinject.Configs( - configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.TxModule(), - configurator.BankModule(), - configurator.StakingModule(), - configurator.ConsensusModule(), - configurator.GovModule(), - configurator.ProtocolPoolModule(), - ), - depinject.Supply(log.NewNopLogger()), - ), - &res.TxConfig, &res.AccountKeeper, &res.BankKeeper, &res.GovKeeper, &res.StakingKeeper) - require.NoError(t, err) - - ctx := app.BaseApp.NewContext(isCheckTx) - - res.App = app - return res, ctx -} - -func getTestingAccounts( - t *testing.T, r *rand.Rand, - accountKeeper authkeeper.AccountKeeper, bankKeeper bankkeeper.Keeper, stakingKeeper *stakingkeeper.Keeper, - ctx sdk.Context, n int, -) []simtypes.Account { - t.Helper() - accounts := simtypes.RandomAccounts(r, n) - - initAmt := stakingKeeper.TokensFromConsensusPower(ctx, 200) - initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) - - // add coins to the accounts - for _, account := range accounts { - acc := accountKeeper.NewAccountWithAddress(ctx, account.Address) - accountKeeper.SetAccount(ctx, acc) - require.NoError(t, testutil.FundAccount(ctx, bankKeeper, account.Address, initCoins)) - } - - return accounts -} diff --git a/tests/sims/nft/app_config.go b/tests/sims/nft/app_config.go deleted file mode 100644 index 7b3a4bb869b3..000000000000 --- a/tests/sims/nft/app_config.go +++ /dev/null @@ -1,27 +0,0 @@ -package nft - -import ( - _ "cosmossdk.io/x/accounts" // import as blank for app wiring - _ "cosmossdk.io/x/bank" // import as blank for app wiring - _ "cosmossdk.io/x/consensus" // import as blank for app wiring - _ "cosmossdk.io/x/mint" // import as blank for app wiring - _ "cosmossdk.io/x/nft/module" // import as blank for app wiring - _ "cosmossdk.io/x/staking" // import as blank for app wiring - - "github.com/cosmos/cosmos-sdk/testutil/configurator" - _ "github.com/cosmos/cosmos-sdk/x/auth" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/genutil" // import as blank for app wiring -) - -var AppConfig = configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.BankModule(), - configurator.StakingModule(), - configurator.TxModule(), - configurator.ConsensusModule(), - configurator.GenutilModule(), - configurator.MintModule(), - configurator.NFTModule(), -) diff --git a/tests/sims/nft/operations_test.go b/tests/sims/nft/operations_test.go deleted file mode 100644 index 1fc693200c85..000000000000 --- a/tests/sims/nft/operations_test.go +++ /dev/null @@ -1,141 +0,0 @@ -package nft - -import ( - "math/rand" - "testing" - "time" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/core/header" - "cosmossdk.io/depinject" - "cosmossdk.io/log" - bankkeeper "cosmossdk.io/x/bank/keeper" - banktestutil "cosmossdk.io/x/bank/testutil" - "cosmossdk.io/x/nft" - nftkeeper "cosmossdk.io/x/nft/keeper" - "cosmossdk.io/x/nft/simulation" - stakingkeeper "cosmossdk.io/x/staking/keeper" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/runtime" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" -) - -type SimTestSuite struct { - suite.Suite - - ctx sdk.Context - - app *runtime.App - codec codec.Codec - interfaceRegistry codectypes.InterfaceRegistry - txConfig client.TxConfig - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.Keeper - stakingKeeper *stakingkeeper.Keeper - nftKeeper nftkeeper.Keeper -} - -func (suite *SimTestSuite) SetupTest() { - app, err := simtestutil.Setup( - depinject.Configs( - AppConfig, - depinject.Supply(log.NewNopLogger()), - ), - &suite.codec, - &suite.interfaceRegistry, - &suite.txConfig, - &suite.accountKeeper, - &suite.bankKeeper, - &suite.stakingKeeper, - &suite.nftKeeper, - ) - suite.Require().NoError(err) - - suite.app = app - suite.ctx = app.BaseApp.NewContext(false) -} - -func (suite *SimTestSuite) TestWeightedOperations() { - weightedOps := simulation.WeightedOperations( - suite.interfaceRegistry, - make(simtypes.AppParams), - suite.codec, - suite.txConfig, - suite.accountKeeper, - suite.bankKeeper, - suite.nftKeeper, - ) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accs := suite.getTestingAccounts(r, 3) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {simulation.WeightSend, nft.ModuleName, simulation.TypeMsgSend}, - } - - for i, w := range weightedOps { - operationMsg, _, err := w.Op()(r, suite.app.BaseApp, suite.ctx, accs, "") - suite.Require().NoError(err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - suite.Require().Equal(expected[i].weight, w.Weight(), "weight should be the same") - suite.Require().Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - suite.Require().Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { - accounts := simtypes.RandomAccounts(r, n) - - initAmt := suite.stakingKeeper.TokensFromConsensusPower(suite.ctx, 200000) - initCoins := sdk.NewCoins(sdk.NewCoin("stake", initAmt)) - - // add coins to the accounts - for _, account := range accounts { - acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, account.Address) - suite.accountKeeper.SetAccount(suite.ctx, acc) - suite.Require().NoError(banktestutil.FundAccount(suite.ctx, suite.bankKeeper, account.Address, initCoins)) - } - - return accounts -} - -func (suite *SimTestSuite) TestSimulateMsgSend() { - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - blockTime := time.Now().UTC() - ctx := suite.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // execute operation - registry := suite.interfaceRegistry - op := simulation.SimulateMsgSend(codec.NewProtoCodec(registry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.nftKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, ctx, accounts, "") - suite.Require().NoError(err) - - var msg nft.MsgSend - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Len(futureOperations, 0) -} - -func TestSimTestSuite(t *testing.T) { - suite.Run(t, new(SimTestSuite)) -} diff --git a/tests/sims/protocolpool/app_config.go b/tests/sims/protocolpool/app_config.go deleted file mode 100644 index d8b1ace75263..000000000000 --- a/tests/sims/protocolpool/app_config.go +++ /dev/null @@ -1,29 +0,0 @@ -package protocolpool - -import ( - _ "cosmossdk.io/x/accounts" // import as blank for app wiring - _ "cosmossdk.io/x/bank" // import as blank for app wiring - _ "cosmossdk.io/x/consensus" // import as blank for app wiring - _ "cosmossdk.io/x/distribution" // import as blank for app wiring - _ "cosmossdk.io/x/mint" // import as blank for app wiring - _ "cosmossdk.io/x/protocolpool" // import as blank for app wiring - _ "cosmossdk.io/x/staking" // import as blank for app wiring - - "github.com/cosmos/cosmos-sdk/testutil/configurator" - _ "github.com/cosmos/cosmos-sdk/x/auth" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/genutil" // import as blank for app wiring -) - -var AppConfig = configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.BankModule(), - configurator.StakingModule(), - configurator.TxModule(), - configurator.ConsensusModule(), - configurator.GenutilModule(), - configurator.DistributionModule(), - configurator.MintModule(), - configurator.ProtocolPoolModule(), -) diff --git a/tests/sims/protocolpool/operations_test.go b/tests/sims/protocolpool/operations_test.go deleted file mode 100644 index dffebefd97b6..000000000000 --- a/tests/sims/protocolpool/operations_test.go +++ /dev/null @@ -1,148 +0,0 @@ -package protocolpool - -import ( - "math/rand" - "testing" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/require" - - "cosmossdk.io/depinject" - "cosmossdk.io/log" - bankkeeper "cosmossdk.io/x/bank/keeper" - banktestutil "cosmossdk.io/x/bank/testutil" - "cosmossdk.io/x/protocolpool/keeper" - "cosmossdk.io/x/protocolpool/simulation" - "cosmossdk.io/x/protocolpool/types" - stakingkeeper "cosmossdk.io/x/staking/keeper" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/runtime" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" -) - -type suite struct { - Ctx sdk.Context - App *runtime.App - - TxConfig client.TxConfig - Cdc codec.Codec - AccountKeeper authkeeper.AccountKeeper - BankKeeper bankkeeper.Keeper - StakingKeeper *stakingkeeper.Keeper - PoolKeeper keeper.Keeper -} - -func setUpTest(t *testing.T) suite { - t.Helper() - res := suite{} - - var ( - appBuilder *runtime.AppBuilder - err error - ) - - app, err := simtestutil.Setup( - depinject.Configs( - AppConfig, - depinject.Supply(log.NewNopLogger()), - ), - &res.AccountKeeper, - &res.BankKeeper, - &res.Cdc, - &appBuilder, - &res.StakingKeeper, - &res.PoolKeeper, - &res.TxConfig, - ) - require.NoError(t, err) - - res.App = app - res.Ctx = app.BaseApp.NewContext(false) - return res -} - -// TestWeightedOperations tests the weights of the operations. -func TestWeightedOperations(t *testing.T) { - suite := setUpTest(t) - - appParams := make(simtypes.AppParams) - - weightedOps := simulation.WeightedOperations(appParams, suite.Cdc, suite.TxConfig, suite.AccountKeeper, - suite.BankKeeper, suite.PoolKeeper) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accs := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, suite.Ctx, 3) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {simulation.DefaultWeightMsgFundCommunityPool, types.ModuleName, sdk.MsgTypeURL(&types.MsgFundCommunityPool{})}, - } - - for i, w := range weightedOps { - operationMsg, _, err := w.Op()(r, suite.App.BaseApp, suite.Ctx, accs, "") - require.NoError(t, err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - require.Equal(t, expected[i].weight, w.Weight(), "weight should be the same") - require.Equal(t, expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - require.Equal(t, expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -// TestSimulateMsgFundCommunityPool tests the normal scenario of a valid message of type TypeMsgFundCommunityPool. -// Abonormal scenarios, where the message is created by an errors, are not tested here. -func TestSimulateMsgFundCommunityPool(t *testing.T) { - suite := setUpTest(t) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, suite.Ctx, 3) - - // execute operation - op := simulation.SimulateMsgFundCommunityPool(suite.TxConfig, suite.AccountKeeper, suite.BankKeeper, suite.PoolKeeper) - operationMsg, futureOperations, err := op(r, suite.App.BaseApp, suite.Ctx, accounts, "") - require.NoError(t, err) - - var msg types.MsgFundCommunityPool - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(t, err) - require.True(t, operationMsg.OK) - require.Equal(t, "4896096stake", msg.Amount.String()) - require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Depositor) - require.Equal(t, sdk.MsgTypeURL(&types.MsgFundCommunityPool{}), sdk.MsgTypeURL(&msg)) - require.Len(t, futureOperations, 0) -} - -func getTestingAccounts( - t *testing.T, r *rand.Rand, - accountKeeper authkeeper.AccountKeeper, bankKeeper bankkeeper.Keeper, - stakingKeeper *stakingkeeper.Keeper, ctx sdk.Context, n int, -) []simtypes.Account { - t.Helper() - accounts := simtypes.RandomAccounts(r, n) - - initAmt := stakingKeeper.TokensFromConsensusPower(ctx, 200) - initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) - - // add coins to the accounts - for _, account := range accounts { - acc := accountKeeper.NewAccountWithAddress(ctx, account.Address) - accountKeeper.SetAccount(ctx, acc) - require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, account.Address, initCoins)) - } - - return accounts -} diff --git a/tests/sims/slashing/app_config.go b/tests/sims/slashing/app_config.go deleted file mode 100644 index f649e196fb75..000000000000 --- a/tests/sims/slashing/app_config.go +++ /dev/null @@ -1,31 +0,0 @@ -package slashing - -import ( - _ "cosmossdk.io/x/accounts" // import as blank for app wiring - _ "cosmossdk.io/x/bank" // import as blank for app wiring - _ "cosmossdk.io/x/consensus" // import as blank for app wiring - _ "cosmossdk.io/x/distribution" // import as blank for app wiring - _ "cosmossdk.io/x/mint" // import as blank for app wiring - _ "cosmossdk.io/x/protocolpool" // import as blank for app wiring - _ "cosmossdk.io/x/slashing" // import as blank for app wiring - _ "cosmossdk.io/x/staking" // import as blank for app wiring - - "github.com/cosmos/cosmos-sdk/testutil/configurator" - _ "github.com/cosmos/cosmos-sdk/x/auth" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/genutil" // import as blank for app wiring -) - -var AppConfig = configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.BankModule(), - configurator.StakingModule(), - configurator.SlashingModule(), - configurator.TxModule(), - configurator.ConsensusModule(), - configurator.GenutilModule(), - configurator.MintModule(), - configurator.DistributionModule(), - configurator.ProtocolPoolModule(), -) diff --git a/tests/sims/slashing/operations_test.go b/tests/sims/slashing/operations_test.go deleted file mode 100644 index f4b6c31773bd..000000000000 --- a/tests/sims/slashing/operations_test.go +++ /dev/null @@ -1,228 +0,0 @@ -package slashing - -import ( - "fmt" - "math/rand" - "testing" - "time" - - abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" - cmttypes "github.com/cometbft/cometbft/types" - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/collections" - "cosmossdk.io/core/header" - "cosmossdk.io/depinject" - "cosmossdk.io/log" - "cosmossdk.io/math" - bankkeeper "cosmossdk.io/x/bank/keeper" - banktestutil "cosmossdk.io/x/bank/testutil" - distributionkeeper "cosmossdk.io/x/distribution/keeper" - distrtypes "cosmossdk.io/x/distribution/types" - mintkeeper "cosmossdk.io/x/mint/keeper" - minttypes "cosmossdk.io/x/mint/types" - slashingkeeper "cosmossdk.io/x/slashing/keeper" - "cosmossdk.io/x/slashing/simulation" - "cosmossdk.io/x/slashing/types" - stakingkeeper "cosmossdk.io/x/staking/keeper" - stakingtypes "cosmossdk.io/x/staking/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - "github.com/cosmos/cosmos-sdk/runtime" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" -) - -type SimTestSuite struct { - suite.Suite - - ctx sdk.Context - r *rand.Rand - accounts []simtypes.Account - - app *runtime.App - codec codec.Codec - interfaceRegistry codectypes.InterfaceRegistry - txConfig client.TxConfig - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.Keeper - stakingKeeper *stakingkeeper.Keeper - slashingKeeper slashingkeeper.Keeper - distrKeeper distributionkeeper.Keeper - mintKeeper mintkeeper.Keeper -} - -func (suite *SimTestSuite) SetupTest() { - s := rand.NewSource(1) - suite.r = rand.New(s) - accounts := simtypes.RandomAccounts(suite.r, 4) - - // create validator (non random as using a seed) - createValidator := func() (*cmttypes.ValidatorSet, error) { - account := accounts[0] - cmtPk, err := cryptocodec.ToCmtPubKeyInterface(account.ConsKey.PubKey()) - if err != nil { - return nil, fmt.Errorf("failed to create pubkey: %w", err) - } - - validator := cmttypes.NewValidator(cmtPk, 1) - - return cmttypes.NewValidatorSet([]*cmttypes.Validator{validator}), nil - } - - startupCfg := simtestutil.DefaultStartUpConfig() - startupCfg.ValidatorSet = createValidator - - app, err := simtestutil.SetupWithConfiguration( - depinject.Configs( - AppConfig, - depinject.Supply(log.NewNopLogger()), - ), - startupCfg, - &suite.codec, - &suite.interfaceRegistry, - &suite.txConfig, - &suite.accountKeeper, - &suite.bankKeeper, - &suite.stakingKeeper, - &suite.mintKeeper, - &suite.slashingKeeper, - &suite.distrKeeper, - ) - - suite.Require().NoError(err) - suite.app = app - suite.ctx = app.BaseApp.NewContext(false) - - // remove genesis validator account - suite.accounts = accounts[1:] - - initAmt := suite.stakingKeeper.TokensFromConsensusPower(suite.ctx, 200) - initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) - - // add coins to the accounts - for _, account := range suite.accounts { - acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, account.Address) - suite.accountKeeper.SetAccount(suite.ctx, acc) - suite.Require().NoError(banktestutil.FundAccount(suite.ctx, suite.bankKeeper, account.Address, initCoins)) - } - suite.Require().NoError(suite.mintKeeper.Params.Set(suite.ctx, minttypes.DefaultParams())) - suite.Require().NoError(suite.mintKeeper.Minter.Set(suite.ctx, minttypes.DefaultInitialMinter())) -} - -func TestSimTestSuite(t *testing.T) { - suite.Run(t, new(SimTestSuite)) -} - -// TestWeightedOperations tests the weights of the operations. -func (suite *SimTestSuite) TestWeightedOperations() { - ctx := suite.ctx.WithChainID("test-chain") - appParams := make(simtypes.AppParams) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {simulation.DefaultWeightMsgUnjail, types.ModuleName, sdk.MsgTypeURL(&types.MsgUnjail{})}, - } - - weightedOps := simulation.WeightedOperations(suite.interfaceRegistry, appParams, suite.codec, suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.slashingKeeper, suite.stakingKeeper) - for i, w := range weightedOps { - operationMsg, _, err := w.Op()(suite.r, suite.app.BaseApp, ctx, suite.accounts, ctx.ChainID()) - suite.Require().NoError(err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - suite.Require().Equal(expected[i].weight, w.Weight(), "weight should be the same") - suite.Require().Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - suite.Require().Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -// TestSimulateMsgUnjail tests the normal scenario of a valid message of type types.MsgUnjail. -// Abonormal scenarios, where the message is created by an errors, are not tested here. -func (suite *SimTestSuite) TestSimulateMsgUnjail() { - blockTime := time.Now().UTC() - ctx := suite.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup accounts[0] as validator0 - validator0, err := getTestingValidator0(ctx, suite.stakingKeeper, suite.accounts) - suite.Require().NoError(err) - - // setup validator0 by consensus address - err = suite.stakingKeeper.SetValidatorByConsAddr(ctx, validator0) - suite.Require().NoError(err) - - val0ConsAddress, err := validator0.GetConsAddr() - suite.Require().NoError(err) - val0ConsAddressStr, err := suite.stakingKeeper.ConsensusAddressCodec().BytesToString(val0ConsAddress) - suite.Require().NoError(err) - info := types.NewValidatorSigningInfo(val0ConsAddressStr, int64(4), - time.Unix(2, 0), false, int64(10)) - err = suite.slashingKeeper.ValidatorSigningInfo.Set(ctx, val0ConsAddress, info) - suite.Require().NoError(err) - // put validator0 in jail - suite.Require().NoError(suite.stakingKeeper.Jail(ctx, val0ConsAddress)) - - // setup self delegation - delTokens := suite.stakingKeeper.TokensFromConsensusPower(ctx, 2) - validator0, issuedShares := validator0.AddTokensFromDel(delTokens) - val0AccAddress, err := sdk.ValAddressFromBech32(validator0.OperatorAddress) - suite.Require().NoError(err) - selfDelegation := stakingtypes.NewDelegation(suite.accounts[0].Address.String(), validator0.GetOperator(), issuedShares) - suite.Require().NoError(suite.stakingKeeper.SetDelegation(ctx, selfDelegation)) - suite.Require().NoError(suite.distrKeeper.DelegatorStartingInfo.Set(ctx, collections.Join(val0AccAddress, sdk.AccAddress(val0AccAddress)), distrtypes.NewDelegatorStartingInfo(2, math.LegacyOneDec(), 200))) - - // begin a new block - _, err = suite.app.FinalizeBlock(&abci.FinalizeBlockRequest{Height: suite.app.LastBlockHeight() + 1, Hash: suite.app.LastCommitID().Hash, Time: blockTime}) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgUnjail(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.slashingKeeper, suite.stakingKeeper) - operationMsg, futureOperations, err := op(suite.r, suite.app.BaseApp, ctx, suite.accounts, "") - suite.Require().NoError(err) - - var msg types.MsgUnjail - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal("cosmosvaloper1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7epjs3u", msg.ValidatorAddr) - suite.Require().Len(futureOperations, 0) -} - -func getTestingValidator0(ctx sdk.Context, stakingKeeper *stakingkeeper.Keeper, accounts []simtypes.Account) (stakingtypes.Validator, error) { - commission0 := stakingtypes.NewCommission(math.LegacyZeroDec(), math.LegacyOneDec(), math.LegacyOneDec()) - return getTestingValidator(ctx, stakingKeeper, accounts, commission0, 0) -} - -func getTestingValidator(ctx sdk.Context, stakingKeeper *stakingkeeper.Keeper, accounts []simtypes.Account, commission stakingtypes.Commission, n int) (stakingtypes.Validator, error) { - account := accounts[n] - valPubKey := account.ConsKey.PubKey() - valAddr := sdk.ValAddress(account.PubKey.Address().Bytes()) - validator, err := stakingtypes.NewValidator(valAddr.String(), valPubKey, stakingtypes.Description{}) - if err != nil { - return stakingtypes.Validator{}, fmt.Errorf("failed to create validator: %w", err) - } - - validator, err = validator.SetInitialCommission(commission) - if err != nil { - return stakingtypes.Validator{}, fmt.Errorf("failed to set initial commission: %w", err) - } - - validator.DelegatorShares = math.LegacyNewDec(100) - validator.Tokens = math.NewInt(1000000) - - err = stakingKeeper.SetValidator(ctx, validator) - if err != nil { - return stakingtypes.Validator{}, err - } - return validator, nil -} diff --git a/tests/systemtests/go.mod b/tests/systemtests/go.mod index 0ab29370379e..eb190514eda7 100644 --- a/tests/systemtests/go.mod +++ b/tests/systemtests/go.mod @@ -13,7 +13,7 @@ require ( github.com/gorilla/mux v1.8.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/spf13/cast v1.7.0 // indirect github.com/spf13/cobra v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect diff --git a/tests/systemtests/go.sum b/tests/systemtests/go.sum index c3c0ea61cb06..acdb5c106ba3 100644 --- a/tests/systemtests/go.sum +++ b/tests/systemtests/go.sum @@ -599,8 +599,8 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/testutil/sims/simulation_helpers.go b/testutil/sims/simulation_helpers.go index a513a783edcf..c3ac6b4c0895 100644 --- a/testutil/sims/simulation_helpers.go +++ b/testutil/sims/simulation_helpers.go @@ -7,79 +7,14 @@ import ( "os" "sync" - dbm "github.com/cosmos/cosmos-db" - corestore "cosmossdk.io/core/store" - "cosmossdk.io/log" storetypes "cosmossdk.io/store/types" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/runtime" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/kv" - "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) -// SetupSimulation creates the config, db (levelDB), temporary directory and logger for the simulation tests. -// If `skip` is false it skips the current test. `skip` should be set using the `FlagEnabledValue` flag. -// Returns error on an invalid db instantiation or temp dir creation. -func SetupSimulation(config simtypes.Config, dirPrefix, dbName string, verbose, skip bool) (corestore.KVStoreWithBatch, string, log.Logger, bool, error) { - if !skip { - return nil, "", nil, true, nil - } - - var logger log.Logger - if verbose { - logger = log.NewLogger(os.Stdout) - } else { - logger = log.NewNopLogger() - } - - dir, err := os.MkdirTemp("", dirPrefix) - if err != nil { - return nil, "", nil, false, err - } - - db, err := dbm.NewDB(dbName, dbm.BackendType(config.DBBackend), dir) - if err != nil { - return nil, "", nil, false, err - } - - return db, dir, logger, false, nil -} - -// SimulationOperations retrieves the simulation params from the provided file path -// and returns all the modules weighted operations -func SimulationOperations(app runtime.AppSimI, cdc codec.Codec, config simtypes.Config, txConfig client.TxConfig) []simtypes.WeightedOperation { - signingCtx := cdc.InterfaceRegistry().SigningContext() - simState := module.SimulationState{ - AppParams: make(simtypes.AppParams), - Cdc: cdc, - AddressCodec: signingCtx.AddressCodec(), - ValidatorCodec: signingCtx.ValidatorAddressCodec(), - TxConfig: txConfig, - BondDenom: sdk.DefaultBondDenom, - } - - if config.ParamsFile != "" { - bz, err := os.ReadFile(config.ParamsFile) - if err != nil { - panic(err) - } - - err = json.Unmarshal(bz, &simState.AppParams) - if err != nil { - panic(err) - } - } - - simState.LegacyProposalContents = app.SimulationManager().GetProposalContents(simState) //nolint:staticcheck // we're testing the old way here - simState.ProposalMsgs = app.SimulationManager().GetProposalMsgs(simState) - return app.SimulationManager().WeightedOperations(simState) -} - // CheckExportSimulation exports the app state and simulation parameters to JSON // if the export paths are defined. func CheckExportSimulation(app runtime.AppSimI, config simtypes.Config, params simtypes.Params) error { @@ -115,10 +50,10 @@ type DBStatsInterface interface { } // PrintStats prints the corresponding statistics from the app DB. -func PrintStats(db DBStatsInterface) { - fmt.Println("\nLevelDB Stats") - fmt.Println(db.Stats()["leveldb.stats"]) - fmt.Println("LevelDB cached block size", db.Stats()["leveldb.cachedblock"]) +func PrintStats(db DBStatsInterface, logLine func(args ...any)) { + logLine("\nLevelDB Stats") + logLine(db.Stats()["leveldb.stats"]) + logLine("LevelDB cached block size", db.Stats()["leveldb.cachedblock"]) } // GetSimulationLog unmarshals the KVPair's Value to the corresponding type based on the diff --git a/testutil/sims/simulation_helpers_test.go b/testutil/sims/simulation_helpers_test.go index 034b7e4346fd..a982c7ffafd4 100644 --- a/testutil/sims/simulation_helpers_test.go +++ b/testutil/sims/simulation_helpers_test.go @@ -51,7 +51,6 @@ func TestGetSimulationLog(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.store, func(t *testing.T) { require.Equal(t, tt.expectedLog, GetSimulationLog(tt.store, decoders, tt.kvPairs, tt.kvPairs), tt.store) }) diff --git a/testutil/sims/state_helpers.go b/testutil/sims/state_helpers.go index 684ef474d724..76d06b8959d6 100644 --- a/testutil/sims/state_helpers.go +++ b/testutil/sims/state_helpers.go @@ -2,6 +2,7 @@ package sims import ( "bufio" + "bytes" "encoding/json" "errors" "io" @@ -36,41 +37,11 @@ const ( ) // AppStateFn returns the initial application state using a genesis or the simulation parameters. -// It calls appStateFnWithExtendedCb with nil rawStateCb. func AppStateFn( - cdc codec.JSONCodec, - addresCodec, validatorCodec address.Codec, - simManager *module.SimulationManager, - genesisState map[string]json.RawMessage, -) simtypes.AppStateFn { - return appStateFnWithExtendedCb(cdc, addresCodec, validatorCodec, simManager, genesisState, nil) -} - -// appStateFnWithExtendedCb returns the initial application state using a genesis or the simulation parameters. -// It calls appStateFnWithExtendedCbs with nil moduleStateCb. -func appStateFnWithExtendedCb( - cdc codec.JSONCodec, - addresCodec, validatorCodec address.Codec, - simManager *module.SimulationManager, - genesisState map[string]json.RawMessage, - rawStateCb func(rawState map[string]json.RawMessage), -) simtypes.AppStateFn { - return appStateFnWithExtendedCbs(cdc, addresCodec, validatorCodec, simManager, genesisState, nil, rawStateCb) -} - -// appStateFnWithExtendedCbs returns the initial application state using a genesis or the simulation parameters. -// It panics if the user provides files for both of them. -// If a file is not given for the genesis or the sim params, it creates a randomized one. -// genesisState is the default genesis state of the whole app. -// moduleStateCb is the callback function to access moduleState. -// rawStateCb is the callback function to extend rawState. -func appStateFnWithExtendedCbs( cdc codec.JSONCodec, addressCodec, validatorCodec address.Codec, - simManager *module.SimulationManager, + modules []module.AppModuleSimulation, genesisState map[string]json.RawMessage, - moduleStateCb func(moduleName string, genesisState interface{}), - rawStateCb func(rawState map[string]json.RawMessage), ) simtypes.AppStateFn { return func( r *rand.Rand, @@ -111,11 +82,11 @@ func appStateFnWithExtendedCbs( if err != nil { panic(err) } - appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState, addressCodec, validatorCodec) + appState, simAccs = AppStateRandomizedFn(modules, r, cdc, accs, genesisTimestamp, appParams, genesisState, addressCodec, validatorCodec) default: appParams := make(simtypes.AppParams) - appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState, addressCodec, validatorCodec) + appState, simAccs = AppStateRandomizedFn(modules, r, cdc, accs, genesisTimestamp, appParams, genesisState, addressCodec, validatorCodec) } rawState := make(map[string]json.RawMessage) @@ -172,17 +143,9 @@ func appStateFnWithExtendedCbs( stakingtypes.ModuleName: stakingState, testutil.BankModuleName: bankState, } { - if moduleStateCb != nil { - moduleStateCb(name, state) - } rawState[name] = cdc.MustMarshalJSON(state) } - // extend state from callback function - if rawStateCb != nil { - rawStateCb(rawState) - } - // replace appstate appState, err = json.Marshal(rawState) if err != nil { @@ -195,7 +158,7 @@ func appStateFnWithExtendedCbs( // AppStateRandomizedFn creates calls each module's GenesisState generator function // and creates the simulation params func AppStateRandomizedFn( - simManager *module.SimulationManager, + modules []module.AppModuleSimulation, r *rand.Rand, cdc codec.JSONCodec, accs []simtypes.Account, @@ -237,8 +200,7 @@ func AppStateRandomizedFn( BondDenom: sdk.DefaultBondDenom, GenTimestamp: genesisTimestamp, } - - simManager.GenerateGenesisStates(simState) + generateGenesisStates(modules, simState) appState, err := json.Marshal(genesisState) if err != nil { @@ -250,31 +212,38 @@ func AppStateRandomizedFn( // AppStateFromGenesisFileFn util function to generate the genesis AppState // from a genesis.json file. -func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile string) (genutiltypes.AppGenesis, []simtypes.Account, error) { +func AppStateFromGenesisFileFn(_ io.Reader, cdc codec.JSONCodec, genesisFile string) (genutiltypes.AppGenesis, []simtypes.Account, error) { file, err := os.Open(filepath.Clean(genesisFile)) if err != nil { panic(err) } + defer file.Close() genesis, err := genutiltypes.AppGenesisFromReader(bufio.NewReader(file)) if err != nil { - return *genesis, nil, err + return genutiltypes.AppGenesis{}, nil, err } - if err := file.Close(); err != nil { - return *genesis, nil, err + appStateJSON := genesis.AppState + newAccs, err := AccountsFromAppState(cdc, appStateJSON) + if err != nil { + panic(err) } + return *genesis, newAccs, nil +} + +func AccountsFromAppState(cdc codec.JSONCodec, appStateJSON json.RawMessage) ([]simtypes.Account, error) { var appState map[string]json.RawMessage - if err = json.Unmarshal(genesis.AppState, &appState); err != nil { - return *genesis, nil, err + if err := json.Unmarshal(appStateJSON, &appState); err != nil { + return nil, err } var authGenesis authtypes.GenesisState if appState[testutil.AuthModuleName] != nil { cdc.MustUnmarshalJSON(appState[testutil.AuthModuleName], &authGenesis) } - + r := bufio.NewReader(bytes.NewReader(appStateJSON)) // any deterministic source newAccs := make([]simtypes.Account, len(authGenesis.Accounts)) for i, acc := range authGenesis.Accounts { // Pick a random private key, since we don't know the actual key @@ -282,20 +251,25 @@ func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile str // and these keys are never actually used to sign by mock CometBFT. privkeySeed := make([]byte, 15) if _, err := r.Read(privkeySeed); err != nil { - panic(err) + return nil, err } privKey := secp256k1.GenPrivKeyFromSecret(privkeySeed) a, ok := acc.GetCachedValue().(sdk.AccountI) if !ok { - return *genesis, nil, errors.New("expected account") + return nil, errors.New("expected account") } // create simulator accounts simAcc := simtypes.Account{PrivKey: privKey, PubKey: privKey.PubKey(), Address: a.GetAddress(), ConsKey: ed25519.GenPrivKeyFromSecret(privkeySeed)} newAccs[i] = simAcc } + return newAccs, nil +} - return *genesis, newAccs, nil +func generateGenesisStates(modules []module.AppModuleSimulation, simState *module.SimulationState) { + for _, m := range modules { + m.GenerateGenesisState(simState) + } } diff --git a/testutils/sims/runner.go b/testutils/sims/runner.go deleted file mode 100644 index e30a252c0d29..000000000000 --- a/testutils/sims/runner.go +++ /dev/null @@ -1,251 +0,0 @@ -package sims - -import ( - "fmt" - "io" - "os" - "path/filepath" - "testing" - - dbm "github.com/cosmos/cosmos-db" - "github.com/stretchr/testify/require" - - corestore "cosmossdk.io/core/store" - "cosmossdk.io/log" - - "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/server" - servertypes "github.com/cosmos/cosmos-sdk/server/types" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" -) - -const SimAppChainID = "simulation-app" - -// this list of seeds was imported from the original simulation runner: https://github.com/cosmos/tools/blob/v1.0.0/cmd/runsim/main.go#L32 -var defaultSeeds = []int64{ - 1, 2, 4, 7, - 32, 123, 124, 582, 1893, 2989, - 3012, 4728, 37827, 981928, 87821, 891823782, - 989182, 89182391, 11, 22, 44, 77, 99, 2020, - 3232, 123123, 124124, 582582, 18931893, - 29892989, 30123012, 47284728, 7601778, 8090485, - 977367484, 491163361, 424254581, 673398983, -} - -type SimStateFactory struct { - Codec codec.Codec - AppStateFn simtypes.AppStateFn - BlockedAddr map[string]bool -} - -// SimulationApp abstract app that is used by sims -type SimulationApp interface { - runtime.AppSimI - SetNotSigverifyTx() - GetBaseApp() *baseapp.BaseApp - TxConfig() client.TxConfig - Close() error -} - -// Run is a helper function that runs a simulation test with the given parameters. -// It calls the RunWithSeeds function with the default seeds and parameters. -// -// This is the entrypoint to run simulation tests that used to run with the runsim binary. -func Run[T SimulationApp]( - t *testing.T, - appFactory func( - logger log.Logger, - db corestore.KVStoreWithBatch, - traceStore io.Writer, - loadLatest bool, - appOpts servertypes.AppOptions, - baseAppOptions ...func(*baseapp.BaseApp), - ) T, - setupStateFactory func(app T) SimStateFactory, - postRunActions ...func(t *testing.T, app TestInstance[T]), -) { - t.Helper() - RunWithSeeds(t, appFactory, setupStateFactory, defaultSeeds, nil, postRunActions...) -} - -// RunWithSeeds is a helper function that runs a simulation test with the given parameters. -// It iterates over the provided seeds and runs the simulation test for each seed in parallel. -// -// It sets up the environment, creates an instance of the simulation app, -// calls the simulation.SimulateFromSeed function to run the simulation, and performs post-run actions for each seed. -// The execution is deterministic and can be used for fuzz tests as well. -// -// The system under test is isolated for each run but unlike the old runsim command, there is no Process separation. -// This means, global caches may be reused for example. This implementation build upon the vanialla Go stdlib test framework. -func RunWithSeeds[T SimulationApp]( - t *testing.T, - appFactory func( - logger log.Logger, - db corestore.KVStoreWithBatch, - traceStore io.Writer, - loadLatest bool, - appOpts servertypes.AppOptions, - baseAppOptions ...func(*baseapp.BaseApp), - ) T, - setupStateFactory func(app T) SimStateFactory, - seeds []int64, - fuzzSeed []byte, - postRunActions ...func(t *testing.T, app TestInstance[T]), -) { - t.Helper() - cfg := cli.NewConfigFromFlags() - cfg.ChainID = SimAppChainID - for i := range seeds { - seed := seeds[i] - t.Run(fmt.Sprintf("seed: %d", seed), func(t *testing.T) { - t.Parallel() - // setup environment - tCfg := cfg.With(t, seed, fuzzSeed) - testInstance := NewSimulationAppInstance(t, tCfg, appFactory) - var runLogger log.Logger - if cli.FlagVerboseValue { - runLogger = log.NewTestLogger(t) - } else { - runLogger = log.NewTestLoggerInfo(t) - } - runLogger = runLogger.With("seed", tCfg.Seed) - app := testInstance.App - stateFactory := setupStateFactory(app) - simParams, err := simulation.SimulateFromSeedX( - t, - runLogger, - WriteToDebugLog(runLogger), - app.GetBaseApp(), - stateFactory.AppStateFn, - simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 - simtestutil.SimulationOperations(app, stateFactory.Codec, tCfg, app.TxConfig()), - stateFactory.BlockedAddr, - tCfg, - stateFactory.Codec, - app.TxConfig().SigningContext().AddressCodec(), - testInstance.ExecLogWriter, - ) - require.NoError(t, err) - err = simtestutil.CheckExportSimulation(app, tCfg, simParams) - require.NoError(t, err) - if tCfg.Commit { - db, ok := testInstance.DB.(simtestutil.DBStatsInterface) - if ok { - simtestutil.PrintStats(db) - } - } - for _, step := range postRunActions { - step(t, testInstance) - } - require.NoError(t, app.Close()) - }) - } -} - -// TestInstance is a generic type that represents an instance of a SimulationApp used for testing simulations. -// It contains the following fields: -// - App: The instance of the SimulationApp under test. -// - DB: The LevelDB database for the simulation app. -// - WorkDir: The temporary working directory for the simulation app. -// - Cfg: The configuration flags for the simulator. -// - AppLogger: The logger used for logging in the app during the simulation, with seed value attached. -// - ExecLogWriter: Captures block and operation data coming from the simulation -type TestInstance[T SimulationApp] struct { - App T - DB corestore.KVStoreWithBatch - WorkDir string - Cfg simtypes.Config - AppLogger log.Logger - ExecLogWriter simulation.LogWriter -} - -// NewSimulationAppInstance initializes and returns a TestInstance of a SimulationApp. -// The function takes a testing.T instance, a simtypes.Config instance, and an appFactory function as parameters. -// It creates a temporary working directory and a LevelDB database for the simulation app. -// The function then initializes a logger based on the verbosity flag and sets the logger's seed to the test configuration's seed. -// The database is closed and cleaned up on test completion. -func NewSimulationAppInstance[T SimulationApp]( - t *testing.T, - tCfg simtypes.Config, - appFactory func(logger log.Logger, db corestore.KVStoreWithBatch, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp)) T, -) TestInstance[T] { - t.Helper() - workDir := t.TempDir() - require.NoError(t, os.Mkdir(filepath.Join(workDir, "data"), 0o755)) - - dbDir := filepath.Join(workDir, "leveldb-app-sim") - var logger log.Logger - if cli.FlagVerboseValue { - logger = log.NewTestLogger(t) - } else { - logger = log.NewTestLoggerError(t) - } - logger = logger.With("seed", tCfg.Seed) - - db, err := dbm.NewDB("Simulation", dbm.BackendType(tCfg.DBBackend), dbDir) - require.NoError(t, err) - t.Cleanup(func() { - _ = db.Close() // ensure db is closed - }) - appOptions := make(simtestutil.AppOptionsMap) - appOptions[flags.FlagHome] = workDir - appOptions[server.FlagInvCheckPeriod] = cli.FlagPeriodValue - - app := appFactory(logger, db, nil, true, appOptions, baseapp.SetChainID(SimAppChainID)) - if !cli.FlagSigverifyTxValue { - app.SetNotSigverifyTx() - } - return TestInstance[T]{ - App: app, - DB: db, - WorkDir: workDir, - Cfg: tCfg, - AppLogger: logger, - ExecLogWriter: &simulation.StandardLogWriter{Seed: tCfg.Seed}, - } -} - -var _ io.Writer = writerFn(nil) - -type writerFn func(p []byte) (n int, err error) - -func (w writerFn) Write(p []byte) (n int, err error) { - return w(p) -} - -// WriteToDebugLog is an adapter to io.Writer interface -func WriteToDebugLog(logger log.Logger) io.Writer { - return writerFn(func(p []byte) (n int, err error) { - logger.Debug(string(p)) - return len(p), nil - }) -} - -// AppOptionsFn is an adapter to the single method AppOptions interface -type AppOptionsFn func(string) any - -func (f AppOptionsFn) Get(k string) any { - return f(k) -} - -func (f AppOptionsFn) GetString(k string) string { - str, ok := f(k).(string) - if !ok { - return "" - } - - return str -} - -// FauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of -// an IAVLStore for faster simulation speed. -func FauxMerkleModeOpt(bapp *baseapp.BaseApp) { - bapp.SetFauxMerkleMode() -} diff --git a/tools/confix/go.mod b/tools/confix/go.mod index 61a003f48483..97ee10d9805c 100644 --- a/tools/confix/go.mod +++ b/tools/confix/go.mod @@ -114,7 +114,7 @@ require ( github.com/petermattis/goid v0.0.0-20240327183114-c42a807a84ba // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/tools/confix/go.sum b/tools/confix/go.sum index 126663680c74..5498f785a963 100644 --- a/tools/confix/go.sum +++ b/tools/confix/go.sum @@ -600,8 +600,8 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/tools/confix/migrations.go b/tools/confix/migrations.go index 437c628d7b25..86bf1affee24 100644 --- a/tools/confix/migrations.go +++ b/tools/confix/migrations.go @@ -74,7 +74,6 @@ func PlanBuilder(from *tomledit.Document, to, planType string, loadFn loadDestCo diffs := DiffKeys(from, target) for _, diff := range diffs { - diff := diff kv := diff.KV var step transform.Step diff --git a/tools/cosmovisor/args_test.go b/tools/cosmovisor/args_test.go index 74b75841ec5d..f121a3989d9f 100644 --- a/tools/cosmovisor/args_test.go +++ b/tools/cosmovisor/args_test.go @@ -765,8 +765,6 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { } for _, tc := range tests { - tc := tc - s.T().Run(tc.name, func(t *testing.T) { s.setEnv(t, &tc.envVals) cfg, err := GetConfigFromEnv(false) diff --git a/tools/cosmovisor/cmd/cosmovisor/init_test.go b/tools/cosmovisor/cmd/cosmovisor/init_test.go index cea1349e3b39..97a082db729b 100644 --- a/tools/cosmovisor/cmd/cosmovisor/init_test.go +++ b/tools/cosmovisor/cmd/cosmovisor/init_test.go @@ -355,8 +355,6 @@ func (s *InitTestSuite) TestInitializeCosmovisorNegativeValidation() { } for _, tc := range tests { - tc := tc - s.T().Run(tc.name, func(t *testing.T) { s.setEnv(t, &tc.env) buffer, logger := s.NewCapturingLogger() diff --git a/tools/cosmovisor/go.mod b/tools/cosmovisor/go.mod index 008d8f1eae5a..5a49c9cd0d6c 100644 --- a/tools/cosmovisor/go.mod +++ b/tools/cosmovisor/go.mod @@ -132,7 +132,7 @@ require ( github.com/petermattis/goid v0.0.0-20240503122002-4b96552b8156 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/tools/cosmovisor/go.sum b/tools/cosmovisor/go.sum index bddec9c4144c..b04b98cc9cc8 100644 --- a/tools/cosmovisor/go.sum +++ b/tools/cosmovisor/go.sum @@ -838,8 +838,8 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/tools/hubl/go.mod b/tools/hubl/go.mod index eb586f655e6d..8727bdb84e8e 100644 --- a/tools/hubl/go.mod +++ b/tools/hubl/go.mod @@ -1,8 +1,6 @@ module cosmossdk.io/tools/hubl -go 1.21.0 - -toolchain go1.23.0 +go 1.23.0 require ( cosmossdk.io/api v0.7.5 @@ -116,7 +114,7 @@ require ( github.com/petermattis/goid v0.0.0-20240327183114-c42a807a84ba // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/tools/hubl/go.sum b/tools/hubl/go.sum index 45f9febb001b..1b2ebc181ed9 100644 --- a/tools/hubl/go.sum +++ b/tools/hubl/go.sum @@ -600,8 +600,8 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/types/address_test.go b/types/address_test.go index 04edc6d6075f..014a48b7386e 100644 --- a/types/address_test.go +++ b/types/address_test.go @@ -422,7 +422,6 @@ func (s *addressTestSuite) TestBech32ifyAddressBytes() { {"20-byte address", args{"prefixb", addr20byte}, "prefixb1qqqsyqcyq5rqwzqfpg9scrgwpugpzysnrujsuw", false}, } for _, tt := range tests { - tt := tt s.T().Run(tt.name, func(t *testing.T) { got, err := types.Bech32ifyAddressBytes(tt.args.prefix, tt.args.bs) if (err != nil) != tt.wantErr { @@ -453,7 +452,6 @@ func (s *addressTestSuite) TestMustBech32ifyAddressBytes() { {"20-byte address", args{"prefixb", addr20byte}, "prefixb1qqqsyqcyq5rqwzqfpg9scrgwpugpzysnrujsuw", false}, } for _, tt := range tests { - tt := tt s.T().Run(tt.name, func(t *testing.T) { if tt.wantPanic { require.Panics(t, func() { types.MustBech32ifyAddressBytes(tt.args.prefix, tt.args.bs) }) diff --git a/types/coin.go b/types/coin.go index 702d8591ddb0..19e002ff0f41 100644 --- a/types/coin.go +++ b/types/coin.go @@ -432,7 +432,6 @@ func (coins Coins) SafeMulInt(x math.Int) (Coins, bool) { res := make(Coins, len(coins)) for i, coin := range coins { - coin := coin res[i] = NewCoin(coin.Denom, coin.Amount.Mul(x)) } @@ -466,7 +465,6 @@ func (coins Coins) SafeQuoInt(x math.Int) (Coins, bool) { var res Coins for _, coin := range coins { - coin := coin res = append(res, NewCoin(coin.Denom, coin.Amount.Quo(x))) } diff --git a/types/coin_test.go b/types/coin_test.go index 5e7389e994ed..0c746ffb6206 100644 --- a/types/coin_test.go +++ b/types/coin_test.go @@ -178,7 +178,6 @@ func (s *coinTestSuite) TestAddCoin() { } for tcIndex, tc := range cases { - tc := tc if tc.shouldPanic { s.Require().Panics(func() { tc.inputOne.Add(tc.inputTwo) }) } else { @@ -218,7 +217,6 @@ func (s *coinTestSuite) TestSubCoin() { } for tcIndex, tc := range cases { - tc := tc if tc.shouldPanic { s.Require().Panics(func() { tc.inputOne.Sub(tc.inputTwo) }) } else { @@ -274,7 +272,6 @@ func (s *coinTestSuite) TestMulIntCoins() { assert := s.Assert() for i, tc := range testCases { - tc := tc if tc.shouldPanic { assert.Panics(func() { tc.input.MulInt(tc.multiplier) }) } else { @@ -301,7 +298,6 @@ func (s *coinTestSuite) TestQuoIntCoins() { assert := s.Assert() for i, tc := range testCases { - tc := tc if tc.shouldPanic { assert.Panics(func() { tc.input.QuoInt(tc.divisor) }) } else { @@ -326,7 +322,6 @@ func (s *coinTestSuite) TestIsGTCoin() { } for tcIndex, tc := range cases { - tc := tc if tc.panics { s.Require().Panics(func() { tc.inputOne.IsGT(tc.inputTwo) }) } else { @@ -350,7 +345,6 @@ func (s *coinTestSuite) TestIsGTECoin() { } for tcIndex, tc := range cases { - tc := tc if tc.panics { s.Require().Panics(func() { tc.inputOne.IsGTE(tc.inputTwo) }) } else { @@ -374,7 +368,6 @@ func (s *coinTestSuite) TestIsLTECoin() { } for tcIndex, tc := range cases { - tc := tc if tc.panics { s.Require().Panics(func() { tc.inputOne.IsLTE(tc.inputTwo) }) } else { @@ -400,7 +393,6 @@ func (s *coinTestSuite) TestIsLTCoin() { } for tcIndex, tc := range cases { - tc := tc if tc.panics { s.Require().Panics(func() { tc.inputOne.IsLT(tc.inputTwo) }) } else { @@ -683,7 +675,6 @@ func (s *coinTestSuite) TestSubCoins() { assert := s.Assert() for i, tc := range testCases { - tc := tc if tc.shouldPanic { assert.Panics(func() { tc.inputOne.Sub(tc.inputTwo...) }) } else { @@ -708,7 +699,7 @@ func (s *coinTestSuite) TestSafeSubCoin() { } for _, tc := range cases { - tc := tc + res, err := tc.inputOne.SafeSub(tc.inputTwo) if err != nil { s.Require().Contains(err.Error(), tc.expErrMsg) @@ -1373,7 +1364,7 @@ func (s *coinTestSuite) TestCoinValidate() { } for _, tc := range testCases { - tc := tc + t := s.T() t.Run(tc.name, func(t *testing.T) { err := tc.coin.Validate() diff --git a/types/context_test.go b/types/context_test.go index 8975c048f01e..d4e738edd156 100644 --- a/types/context_test.go +++ b/types/context_test.go @@ -203,7 +203,6 @@ func (s *contextTestSuite) TestContextHeaderClone() { } for name, tc := range cases { - tc := tc s.T().Run(name, func(t *testing.T) { ctx := types.NewContext(nil, false, nil).WithBlockHeader(tc.h) s.Require().Equal(tc.h.Height, ctx.BlockHeight()) diff --git a/types/dec_coin_test.go b/types/dec_coin_test.go index e71626b4ec49..486f72711b32 100644 --- a/types/dec_coin_test.go +++ b/types/dec_coin_test.go @@ -211,7 +211,6 @@ func (s *decCoinTestSuite) TestIsValid() { } for _, tc := range tests { - tc := tc if tc.expectPass { s.Require().True(tc.coin.IsValid(), tc.msg) } else { @@ -246,7 +245,6 @@ func (s *decCoinTestSuite) TestSubDecCoin() { decCoin := sdk.NewDecCoin("mytoken", math.NewInt(10)) for _, tc := range tests { - tc := tc if tc.expectPass { equal := tc.coin.Sub(decCoin) s.Require().Equal(equal, decCoin, tc.msg) @@ -282,7 +280,6 @@ func (s *decCoinTestSuite) TestSubDecCoins() { decCoins := sdk.NewDecCoinsFromCoins(sdk.NewCoin("btc", math.NewInt(10)), sdk.NewCoin("eth", math.NewInt(15)), sdk.NewCoin("mytoken", math.NewInt(5))) for _, tc := range tests { - tc := tc if tc.expectPass { equal := tc.coins.Sub(decCoins) s.Require().Equal(equal, decCoins, tc.msg) @@ -527,7 +524,6 @@ func (s *decCoinTestSuite) TestDecCoinsQuoDecTruncate() { } for i, tc := range testCases { - tc := tc if tc.panics { s.Require().Panics(func() { tc.coins.QuoDecTruncate(tc.input) }) } else { @@ -564,7 +560,6 @@ func (s *decCoinTestSuite) TestNewDecCoinsWithIsValid() { } for _, tc := range tests { - tc := tc if tc.expectPass { s.Require().True(tc.coin.IsValid(), tc.msg) } else { @@ -591,7 +586,6 @@ func (s *decCoinTestSuite) TestNewDecCoinsWithZeroCoins() { } for _, tc := range tests { - tc := tc s.Require().Equal(sdk.NewDecCoinsFromCoins(tc.coins...).Len(), tc.expectLength) } } @@ -623,7 +617,6 @@ func (s *decCoinTestSuite) TestDecCoins_AddDecCoinWithIsValid() { } for _, tc := range tests { - tc := tc if tc.expectPass { s.Require().True(tc.coin.IsValid(), tc.msg) } else { @@ -679,7 +672,6 @@ func (s *decCoinTestSuite) TestDecCoins_GetDenomByIndex() { } for i, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { if tc.expectedErr { s.Require().Panics(func() { tc.input.GetDenomByIndex(tc.index) }, "Test should have panicked") @@ -721,7 +713,6 @@ func (s *decCoinTestSuite) TestDecCoins_IsAllPositive() { } for i, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { if tc.expectedResult { s.Require().True(tc.input.IsAllPositive(), "Test case #%d: %s", i, tc.name) @@ -791,7 +782,6 @@ func (s *decCoinTestSuite) TestDecCoin_IsGTE() { } for i, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { if tc.expectedPanic { s.Require().Panics(func() { tc.coin.IsGTE(tc.otherCoin) }, "Test case #%d: %s", i, tc.name) @@ -835,7 +825,6 @@ func (s *decCoinTestSuite) TestDecCoins_IsZero() { } for i, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { if tc.expectedResult { s.Require().True(tc.coins.IsZero(), "Test case #%d: %s", i, tc.name) @@ -890,7 +879,6 @@ func (s *decCoinTestSuite) TestDecCoins_MulDec() { } for i, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { res := tc.coins.MulDec(tc.multiplier) s.Require().Equal(tc.expectedResult, res, "Test case #%d: %s", i, tc.name) @@ -939,7 +927,6 @@ func (s *decCoinTestSuite) TestDecCoins_MulDecTruncate() { } for i, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { if tc.expectedPanic { s.Require().Panics(func() { tc.coins.MulDecTruncate(tc.multiplier) }, "Test case #%d: %s", i, tc.name) @@ -992,7 +979,6 @@ func (s *decCoinTestSuite) TestDecCoins_QuoDec() { } for i, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { if tc.panics { s.Require().Panics(func() { tc.coins.QuoDec(tc.input) }, "Test case #%d: %s", i, tc.name) diff --git a/types/events_test.go b/types/events_test.go index 2b55952a9d6d..ae69f0e86531 100644 --- a/types/events_test.go +++ b/types/events_test.go @@ -268,7 +268,6 @@ func (s *eventsTestSuite) TestMarkEventsToIndex() { } for name, tc := range testCases { - tc := tc s.T().Run(name, func(_ *testing.T) { s.Require().Equal(tc.expected, sdk.MarkEventsToIndex(tc.events, tc.indexSet)) }) diff --git a/types/mempool/mempool.go b/types/mempool/mempool.go index 4f8f82f16fa7..6aa29ff3263c 100644 --- a/types/mempool/mempool.go +++ b/types/mempool/mempool.go @@ -14,10 +14,10 @@ type Mempool interface { // Select returns an Iterator over the app-side mempool. If txs are specified, // then they shall be incorporated into the Iterator. The Iterator is not thread-safe to use. - Select(context.Context, [][]byte) Iterator + Select(context.Context, []sdk.Tx) Iterator // SelectBy use callback to iterate over the mempool, it's thread-safe to use. - SelectBy(context.Context, [][]byte, func(sdk.Tx) bool) + SelectBy(context.Context, []sdk.Tx, func(sdk.Tx) bool) // CountTx returns the number of transactions currently in the mempool. CountTx() int diff --git a/types/mempool/noop.go b/types/mempool/noop.go index 33c002080f82..6f9bbf9ae83a 100644 --- a/types/mempool/noop.go +++ b/types/mempool/noop.go @@ -17,7 +17,7 @@ var _ Mempool = (*NoOpMempool)(nil) type NoOpMempool struct{} func (NoOpMempool) Insert(context.Context, sdk.Tx) error { return nil } -func (NoOpMempool) Select(context.Context, [][]byte) Iterator { return nil } -func (NoOpMempool) SelectBy(context.Context, [][]byte, func(sdk.Tx) bool) {} +func (NoOpMempool) Select(context.Context, []sdk.Tx) Iterator { return nil } +func (NoOpMempool) SelectBy(context.Context, []sdk.Tx, func(sdk.Tx) bool) {} func (NoOpMempool) CountTx() int { return 0 } func (NoOpMempool) Remove(sdk.Tx) error { return nil } diff --git a/types/mempool/priority_nonce.go b/types/mempool/priority_nonce.go index c0f16a16002c..b324801ff5ec 100644 --- a/types/mempool/priority_nonce.go +++ b/types/mempool/priority_nonce.go @@ -361,13 +361,13 @@ func (i *PriorityNonceIterator[C]) Tx() sdk.Tx { // // NOTE: It is not safe to use this iterator while removing transactions from // the underlying mempool. -func (mp *PriorityNonceMempool[C]) Select(ctx context.Context, txs [][]byte) Iterator { +func (mp *PriorityNonceMempool[C]) Select(ctx context.Context, txs []sdk.Tx) Iterator { mp.mtx.Lock() defer mp.mtx.Unlock() return mp.doSelect(ctx, txs) } -func (mp *PriorityNonceMempool[C]) doSelect(_ context.Context, _ [][]byte) Iterator { +func (mp *PriorityNonceMempool[C]) doSelect(_ context.Context, _ []sdk.Tx) Iterator { if mp.priorityIndex.Len() == 0 { return nil } @@ -383,7 +383,7 @@ func (mp *PriorityNonceMempool[C]) doSelect(_ context.Context, _ [][]byte) Itera } // SelectBy will hold the mutex during the iteration, callback returns if continue. -func (mp *PriorityNonceMempool[C]) SelectBy(ctx context.Context, txs [][]byte, callback func(sdk.Tx) bool) { +func (mp *PriorityNonceMempool[C]) SelectBy(ctx context.Context, txs []sdk.Tx, callback func(sdk.Tx) bool) { mp.mtx.Lock() defer mp.mtx.Unlock() diff --git a/types/mempool/sender_nonce.go b/types/mempool/sender_nonce.go index f9cb9f200a23..60d1e2991940 100644 --- a/types/mempool/sender_nonce.go +++ b/types/mempool/sender_nonce.go @@ -167,13 +167,13 @@ func (snm *SenderNonceMempool) Insert(_ context.Context, tx sdk.Tx) error { // // NOTE: It is not safe to use this iterator while removing transactions from // the underlying mempool. -func (snm *SenderNonceMempool) Select(ctx context.Context, txs [][]byte) Iterator { +func (snm *SenderNonceMempool) Select(ctx context.Context, txs []sdk.Tx) Iterator { snm.mtx.Lock() defer snm.mtx.Unlock() return snm.doSelect(ctx, txs) } -func (snm *SenderNonceMempool) doSelect(_ context.Context, _ [][]byte) Iterator { +func (snm *SenderNonceMempool) doSelect(_ context.Context, _ []sdk.Tx) Iterator { var senders []string senderCursors := make(map[string]*skiplist.Element) @@ -202,7 +202,7 @@ func (snm *SenderNonceMempool) doSelect(_ context.Context, _ [][]byte) Iterator } // SelectBy will hold the mutex during the iteration, callback returns if continue. -func (snm *SenderNonceMempool) SelectBy(ctx context.Context, txs [][]byte, callback func(sdk.Tx) bool) { +func (snm *SenderNonceMempool) SelectBy(ctx context.Context, txs []sdk.Tx, callback func(sdk.Tx) bool) { snm.mtx.Lock() defer snm.mtx.Unlock() diff --git a/types/module/module.go b/types/module/module.go index 4d947fe2d7ac..7d865930b26b 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -594,7 +594,6 @@ func (m *Manager) assertNoForgottenModules(setOrderFnName string, moduleNames [] } var missing []string for m := range m.Modules { - m := m if pass != nil && pass(m) { continue } @@ -834,7 +833,6 @@ func (m *Manager) GetVersionMap() appmodule.VersionMap { if v, ok := v.(appmodule.HasConsensusVersion); ok { version = v.ConsensusVersion() } - name := name vermap[name] = version } diff --git a/types/module/simulation.go b/types/module/simulation.go index 20bb46ba1976..57e31171b5bd 100644 --- a/types/module/simulation.go +++ b/types/module/simulation.go @@ -18,27 +18,31 @@ import ( // AppModuleSimulation defines the standard functions that every module should expose // for the SDK blockchain simulator type AppModuleSimulation interface { - // randomized genesis states + // GenerateGenesisState randomized genesis states GenerateGenesisState(input *SimulationState) - // register a func to decode the each module's defined types from their corresponding store key + // RegisterStoreDecoder register a func to decode the each module's defined types from their corresponding store key RegisterStoreDecoder(simulation.StoreDecoderRegistry) - - // simulation operations (i.e msgs) with their respective weight - WeightedOperations(simState SimulationState) []simulation.WeightedOperation -} - -// HasProposalMsgs defines the messages that can be used to simulate governance (v1) proposals -type HasProposalMsgs interface { - // msg functions used to simulate governance proposals - ProposalMsgs(simState SimulationState) []simulation.WeightedProposalMsg } +type ( + HasLegacyWeightedOperations interface { + // WeightedOperations simulation operations (i.e msgs) with their respective weight + WeightedOperations(simState SimulationState) []simulation.WeightedOperation + } + // HasLegacyProposalMsgs defines the messages that can be used to simulate governance (v1) proposals + // Deprecated replaced by HasProposalMsgsX + HasLegacyProposalMsgs interface { + // ProposalMsgs msg functions used to simulate governance proposals + ProposalMsgs(simState SimulationState) []simulation.WeightedProposalMsg + } -// HasProposalContents defines the contents that can be used to simulate legacy governance (v1beta1) proposals -type HasProposalContents interface { - // content functions used to simulate governance proposals - ProposalContents(simState SimulationState) []simulation.WeightedProposalContent //nolint:staticcheck // legacy v1beta1 governance -} + // HasLegacyProposalContents defines the contents that can be used to simulate legacy governance (v1beta1) proposals + // Deprecated replaced by HasProposalMsgsX + HasLegacyProposalContents interface { + // ProposalContents content functions used to simulate governance proposals + ProposalContents(simState SimulationState) []simulation.WeightedProposalContent //nolint:staticcheck // legacy v1beta1 governance + } +) // SimulationManager defines a simulation manager that provides the high level utility // for managing and executing simulation functionalities for a group of modules @@ -64,14 +68,13 @@ func NewSimulationManager(modules ...AppModuleSimulation) *SimulationManager { // Then it attempts to cast every provided AppModule into an AppModuleSimulation. // If the cast succeeds, its included, otherwise it is excluded. func NewSimulationManagerFromAppModules(modules map[string]appmodule.AppModule, overrideModules map[string]AppModuleSimulation) *SimulationManager { - simModules := []AppModuleSimulation{} appModuleNamesSorted := make([]string, 0, len(modules)) for moduleName := range modules { appModuleNamesSorted = append(appModuleNamesSorted, moduleName) } - sort.Strings(appModuleNamesSorted) + var simModules []AppModuleSimulation for _, moduleName := range appModuleNamesSorted { // for every module, see if we override it. If so, use override. // Else, if we can cast the app module into a simulation module add it. @@ -95,7 +98,7 @@ func NewSimulationManagerFromAppModules(modules map[string]appmodule.AppModule, func (sm *SimulationManager) GetProposalContents(simState SimulationState) []simulation.WeightedProposalContent { wContents := make([]simulation.WeightedProposalContent, 0, len(sm.Modules)) for _, module := range sm.Modules { - if module, ok := module.(HasProposalContents); ok { + if module, ok := module.(HasLegacyProposalContents); ok { wContents = append(wContents, module.ProposalContents(simState)...) } } @@ -103,19 +106,6 @@ func (sm *SimulationManager) GetProposalContents(simState SimulationState) []sim return wContents } -// GetProposalMsgs returns each module's proposal msg generator function -// with their default operation weight and key. -func (sm *SimulationManager) GetProposalMsgs(simState SimulationState) []simulation.WeightedProposalMsg { - wContents := make([]simulation.WeightedProposalMsg, 0, len(sm.Modules)) - for _, module := range sm.Modules { - if module, ok := module.(HasProposalMsgs); ok { - wContents = append(wContents, module.ProposalMsgs(simState)...) - } - } - - return wContents -} - // RegisterStoreDecoders registers each of the modules' store decoders into a map func (sm *SimulationManager) RegisterStoreDecoders() { for _, module := range sm.Modules { @@ -131,16 +121,6 @@ func (sm *SimulationManager) GenerateGenesisStates(simState *SimulationState) { } } -// WeightedOperations returns all the modules' weighted operations of an application -func (sm *SimulationManager) WeightedOperations(simState SimulationState) []simulation.WeightedOperation { - wOps := make([]simulation.WeightedOperation, 0, len(sm.Modules)) - for _, module := range sm.Modules { - wOps = append(wOps, module.WeightedOperations(simState)...) - } - - return wOps -} - // SimulationState is the input parameters used on each of the module's randomized // GenesisState generator function type SimulationState struct { @@ -158,7 +138,4 @@ type SimulationState struct { GenTimestamp time.Time // genesis timestamp UnbondTime time.Duration // staking unbond time stored to use it as the slashing maximum evidence duration LegacyParamChange []simulation.LegacyParamChange // simulated parameter changes from modules - //nolint:staticcheck // legacy used for testing - LegacyProposalContents []simulation.WeightedProposalContent // proposal content generator functions with their default weight and app sim key - ProposalMsgs []simulation.WeightedProposalMsg // proposal msg generator functions with their default weight and app sim key } diff --git a/types/query/collections_pagination_test.go b/types/query/collections_pagination_test.go index 0e76b28c7a00..25dc267a4481 100644 --- a/types/query/collections_pagination_test.go +++ b/types/query/collections_pagination_test.go @@ -140,7 +140,6 @@ func TestCollectionPagination(t *testing.T) { } for name, tc := range tcs { - tc := tc t.Run(name, func(t *testing.T) { gotResults, gotResponse, err := CollectionFilteredPaginate( ctx, diff --git a/types/simulation/account.go b/types/simulation/account.go index d046ea23e284..0bc7c79fc1f3 100644 --- a/types/simulation/account.go +++ b/types/simulation/account.go @@ -14,10 +14,11 @@ import ( // eventually more useful data can be placed in here. // (e.g. number of coins) type Account struct { - PrivKey cryptotypes.PrivKey - PubKey cryptotypes.PubKey - Address sdk.AccAddress - ConsKey cryptotypes.PrivKey + PrivKey cryptotypes.PrivKey + PubKey cryptotypes.PubKey + Address sdk.AccAddress + ConsKey cryptotypes.PrivKey + AddressBech32 string } // Equals returns true if two accounts are equal @@ -50,10 +51,11 @@ func RandomAccounts(r *rand.Rand, n int) []Account { } idx[string(addr.Bytes())] = struct{}{} accs[i] = Account{ - Address: addr, - PrivKey: privKey, - PubKey: pubKey, - ConsKey: ed25519.GenPrivKeyFromSecret(privkeySeed), + Address: addr, + PrivKey: privKey, + PubKey: pubKey, + ConsKey: ed25519.GenPrivKeyFromSecret(privkeySeed), + AddressBech32: addr.String(), } i++ } diff --git a/types/simulation/account_test.go b/types/simulation/account_test.go index 276d16910e08..a7b806d8b76b 100644 --- a/types/simulation/account_test.go +++ b/types/simulation/account_test.go @@ -24,7 +24,6 @@ func TestRandomAccounts(t *testing.T) { {"100-accounts", 100, 100}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { got := simulation.RandomAccounts(r, tt.n) require.Equal(t, tt.want, len(got)) @@ -66,8 +65,6 @@ func TestRandomFees(t *testing.T) { {"1 coin with 0 amount", sdk.Coins{sdk.NewInt64Coin("ccc", 0)}, true, true}, } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := simulation.RandomFees(r, tt.spendableCoins) if (err != nil) != tt.wantErr { diff --git a/types/simulation/collections.go b/types/simulation/collections.go index 950068fc4835..f3c749bb25a7 100644 --- a/types/simulation/collections.go +++ b/types/simulation/collections.go @@ -10,6 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/kv" ) +// NewStoreDecoderFuncFromCollectionsSchema returns a function that decodes two kv pairs when the module fully uses collections func NewStoreDecoderFuncFromCollectionsSchema(schema collections.Schema) func(kvA, kvB kv.Pair) string { colls := schema.ListCollections() prefixes := make([][]byte, len(colls)) diff --git a/types/simulation/config.go b/types/simulation/config.go index 07cd6d4c69d5..6f93684d0822 100644 --- a/types/simulation/config.go +++ b/types/simulation/config.go @@ -25,7 +25,8 @@ type Config struct { DBBackend string // custom db backend type BlockMaxGas int64 // custom max gas for block FuzzSeed []byte - T testing.TB + TB testing.TB + FauxMerkle bool } func (c Config) shallowCopy() Config { @@ -33,10 +34,10 @@ func (c Config) shallowCopy() Config { } // With sets the values of t, seed, and fuzzSeed in a copy of the Config and returns the copy. -func (c Config) With(t *testing.T, seed int64, fuzzSeed []byte) Config { - t.Helper() +func (c Config) With(tb testing.TB, seed int64, fuzzSeed []byte) Config { + tb.Helper() r := c.shallowCopy() - r.T = t + r.TB = tb r.Seed = seed r.FuzzSeed = fuzzSeed return r diff --git a/types/simulation/rand_util_test.go b/types/simulation/rand_util_test.go index d8704f69f01f..23270aa806c9 100644 --- a/types/simulation/rand_util_test.go +++ b/types/simulation/rand_util_test.go @@ -28,7 +28,6 @@ func TestRandSubsetCoins(t *testing.T) { {"too small amount", rand.New(rand.NewSource(99)), sdk.Coins{sdk.Coin{Denom: "aaa", Amount: math.NewInt(0)}}}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { got := simulation.RandSubsetCoins(tt.r, tt.coins) gotStringRep := got.String() diff --git a/types/simulation/types.go b/types/simulation/types.go index c576b2885d06..cf0fbe1b1816 100644 --- a/types/simulation/types.go +++ b/types/simulation/types.go @@ -3,12 +3,9 @@ package simulation import ( "context" "encoding/json" - "fmt" "math/rand" "time" - "github.com/cosmos/gogoproto/proto" - "cosmossdk.io/core/address" sdk "github.com/cosmos/cosmos-sdk/types" @@ -20,6 +17,17 @@ type AppEntrypoint interface { SimDeliver(_txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) } +var _ AppEntrypoint = SimDeliverFn(nil) + +type ( + AppEntrypointFn = SimDeliverFn + SimDeliverFn func(_txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) +) + +func (m SimDeliverFn) SimDeliver(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) { + return m(txEncoder, tx) +} + // Deprecated: Use WeightedProposalMsg instead. type WeightedProposalContent interface { AppParamsKey() string // key used to retrieve the value of the weight from the simulation application params @@ -28,7 +36,7 @@ type WeightedProposalContent interface { } // Deprecated: Use MsgSimulatorFn instead. -type ContentSimulatorFn func(r *rand.Rand, ctx sdk.Context, accs []Account) Content +type ContentSimulatorFn func(r *rand.Rand, ctx context.Context, accs []Account) Content // Deprecated: Use MsgSimulatorFn instead. type Content interface { @@ -85,17 +93,15 @@ type OperationMsg struct { Name string `json:"name" yaml:"name"` // operation name (msg Type or "no-operation") Comment string `json:"comment" yaml:"comment"` // additional comment OK bool `json:"ok" yaml:"ok"` // success - Msg []byte `json:"msg" yaml:"msg"` // protobuf encoded msg } // NewOperationMsgBasic creates a new operation message from raw input. -func NewOperationMsgBasic(moduleName, msgType, comment string, ok bool, msg []byte) OperationMsg { +func NewOperationMsgBasic(moduleName, msgType, comment string, ok bool) OperationMsg { return OperationMsg{ Route: moduleName, Name: msgType, Comment: comment, OK: ok, - Msg: msg, } } @@ -106,17 +112,12 @@ func NewOperationMsg(msg sdk.Msg, ok bool, comment string) OperationMsg { if moduleName == "" { moduleName = msgType } - protoBz, err := proto.Marshal(msg) - if err != nil { - panic(fmt.Errorf("failed to marshal proto message: %w", err)) - } - - return NewOperationMsgBasic(moduleName, msgType, comment, ok, protoBz) + return NewOperationMsgBasic(moduleName, msgType, comment, ok) } // NoOpMsg - create a no-operation message func NoOpMsg(moduleName, msgType, comment string) OperationMsg { - return NewOperationMsgBasic(moduleName, msgType, comment, false, nil) + return NewOperationMsgBasic(moduleName, msgType, comment, false) } // log entry text for this operation msg diff --git a/types/tx/direct_aux_test.go b/types/tx/direct_aux_test.go index f9e90b8e27e7..a1b655531eaa 100644 --- a/types/tx/direct_aux_test.go +++ b/types/tx/direct_aux_test.go @@ -33,7 +33,6 @@ func TestSignDocDirectAux(t *testing.T) { } for _, tc := range testcases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := tc.sd.ValidateBasic() @@ -68,7 +67,6 @@ func TestAuxSignerData(t *testing.T) { } for _, tc := range testcases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := tc.sd.ValidateBasic() diff --git a/types/utils_test.go b/types/utils_test.go index 22675a2c5990..4c74dfd438d3 100644 --- a/types/utils_test.go +++ b/types/utils_test.go @@ -33,7 +33,7 @@ func (s *utilsTestSuite) TestTimeFormatAndParse() { {"2011-01-10T23:10:05.758230235Z", "2011-01-10T23:10:05.758230235", true}, } for _, tc := range cases { - tc := tc + timeFromRFC, err := time.Parse(time.RFC3339Nano, tc.RFC3339NanoStr) s.Require().Nil(err) timeFromSDKFormat, err := time.Parse(sdk.SortableTimeFormat, tc.SDKSortableTimeStr) @@ -116,8 +116,6 @@ func (s *utilsTestSuite) TestParseTime() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { tm, err := sdk.ParseTime(tc.input) if tc.expectErr { diff --git a/x/accounts/README.md b/x/accounts/README.md index 3bc9e1d48635..8214220d856c 100644 --- a/x/accounts/README.md +++ b/x/accounts/README.md @@ -2,6 +2,63 @@ The x/accounts module provides module and facilities for writing smart cosmos-sdk accounts. +# Supporting Custom Accounts in the x/auth gRPC Server + +## Overview + +The x/auth module provides a mechanism for custom account types to be exposed via its `Account` and `AccountInfo` gRPC +queries. This feature is particularly useful for ensuring compatibility with existing wallets that have not yet integrated +with x/accounts but still need to parse account information post-migration. + +## Implementation + +To support this feature, your custom account type needs to implement the `auth.QueryLegacyAccount` handler. Here are some important points to consider: + +1. **Selective Implementation**: This implementation is not required for every account type. It's only necessary for accounts you want to expose through the x/auth gRPC `Account` and `AccountInfo` methods. +2. **Flexible Response**: The `info` field in the `QueryLegacyAccountResponse` is optional. If your custom account cannot be represented as a `BaseAccount`, you can leave this field empty. + +## Example Implementation + +A concrete example of implementation can be found in `defaults/base/account.go`. Here's a simplified version: + +```go +func (a Account) AuthRetroCompatibility(ctx context.Context, _ *authtypes.QueryLegacyAccount) (*authtypes.QueryLegacyAccountResponse, error) { + seq := a.GetSequence() + num := a.GetNumber() + address := a.GetAddress() + pubKey := a.GetPubKey() + + baseAccount := &authtypes.BaseAccount{ + AccountNumber: num, + Sequence: seq, + Address: address, + } + + // Convert pubKey to Any type + pubKeyAny, err := gogotypes.NewAnyWithValue(pubKey) + if err != nil { + return nil, err + } + baseAccount.PubKey = pubKeyAny + + // Convert the entire baseAccount to Any type + accountAny, err := gogotypes.NewAnyWithValue(baseAccount) + if err != nil { + return nil, err + } + + return &authtypes.QueryLegacyAccountResponse{ + Account: accountAny, + Info: baseAccount, + }, nil +} +``` + +## Usage Notes + +- Implement this handler only for account types you want to expose via x/auth gRPC methods. +- The `info` field in the response can be nil if your account doesn't fit the `BaseAccount` structure. + # Genesis ## Creating accounts on genesis diff --git a/x/accounts/accountstd/exports.go b/x/accounts/accountstd/exports.go index 24ffc17c1e98..973a16c4b2cb 100644 --- a/x/accounts/accountstd/exports.go +++ b/x/accounts/accountstd/exports.go @@ -4,6 +4,7 @@ package accountstd import ( "bytes" "context" + "errors" "fmt" "cosmossdk.io/core/transaction" @@ -13,7 +14,10 @@ import ( "github.com/cosmos/cosmos-sdk/types/address" ) -var accountsModuleAddress = address.Module("accounts") +var ( + accountsModuleAddress = address.Module("accounts") + ErrInvalidType = errors.New("invalid type") +) // Interface is the exported interface of an Account. type Interface = implementation.Account @@ -91,13 +95,21 @@ func SenderIsAccountsModule(ctx context.Context) bool { // returns nil. func Funds(ctx context.Context) sdk.Coins { return implementation.Funds(ctx) } -func ExecModule(ctx context.Context, msg transaction.Msg) (transaction.Msg, error) { - return implementation.ExecModule(ctx, msg) +func ExecModule[MsgResp, Msg transaction.Msg](ctx context.Context, msg Msg) (resp MsgResp, err error) { + untyped, err := implementation.ExecModule(ctx, msg) + if err != nil { + return resp, err + } + return assertOrErr[MsgResp](untyped) } // QueryModule can be used by an account to execute a module query. -func QueryModule(ctx context.Context, req transaction.Msg) (transaction.Msg, error) { - return implementation.QueryModule(ctx, req) +func QueryModule[Resp, Req transaction.Msg](ctx context.Context, req Req) (resp Resp, err error) { + untyped, err := implementation.QueryModule(ctx, req) + if err != nil { + return resp, err + } + return assertOrErr[Resp](untyped) } // UnpackAny unpacks a protobuf Any message generically. @@ -120,7 +132,7 @@ func ExecModuleAnys(ctx context.Context, msgs []*implementation.Any) ([]*impleme if err != nil { return nil, fmt.Errorf("error unpacking message %d: %w", i, err) } - resp, err := ExecModule(ctx, concreteMessage) + resp, err := implementation.ExecModule(ctx, concreteMessage) if err != nil { return nil, fmt.Errorf("error executing message %d: %w", i, err) } @@ -133,3 +145,12 @@ func ExecModuleAnys(ctx context.Context, msgs []*implementation.Any) ([]*impleme } return responses, nil } + +// asserts the given any to the provided generic, returns ErrInvalidType if it can't. +func assertOrErr[T any](r any) (concrete T, err error) { + concrete, ok := r.(T) + if !ok { + return concrete, ErrInvalidType + } + return concrete, nil +} diff --git a/x/accounts/cli/cli_test.go b/x/accounts/cli/cli_test.go index aa5c2521852d..5e9c188d1d68 100644 --- a/x/accounts/cli/cli_test.go +++ b/x/accounts/cli/cli_test.go @@ -119,7 +119,6 @@ func (s *CLITestSuite) TestTxInitCmd() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { ctx := svrcmd.CreateExecuteContext(context.Background()) diff --git a/x/accounts/defaults/base/CHANGELOG.md b/x/accounts/defaults/base/CHANGELOG.md new file mode 100644 index 000000000000..7ce64dffb257 --- /dev/null +++ b/x/accounts/defaults/base/CHANGELOG.md @@ -0,0 +1,26 @@ + + +# Changelog + +## [Unreleased] \ No newline at end of file diff --git a/x/accounts/defaults/base/account.go b/x/accounts/defaults/base/account.go index eef6e6c2153e..ba0f711150b1 100644 --- a/x/accounts/defaults/base/account.go +++ b/x/accounts/defaults/base/account.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" + gogotypes "github.com/cosmos/gogoproto/types/any" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" @@ -21,6 +22,7 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/types/tx" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) var ( @@ -168,17 +170,12 @@ func (a Account) computeSignerData(ctx context.Context) (PubKey, signing.SignerD } func (a Account) getNumber(ctx context.Context, addrStr string) (uint64, error) { - accNum, err := accountstd.QueryModule(ctx, &accountsv1.AccountNumberRequest{Address: addrStr}) + accNum, err := accountstd.QueryModule[*accountsv1.AccountNumberResponse](ctx, &accountsv1.AccountNumberRequest{Address: addrStr}) if err != nil { return 0, err } - resp, ok := accNum.(*accountsv1.AccountNumberResponse) - if !ok { - return 0, fmt.Errorf("unexpected response type: %T", accNum) - } - - return resp.Number, nil + return accNum.Number, nil } func (a Account) getTxData(msg *aa_interface_v1.MsgAuthenticate) (signing.TxData, error) { @@ -261,6 +258,48 @@ func (a Account) QuerySequence(ctx context.Context, _ *v1.QuerySequence) (*v1.Qu return &v1.QuerySequenceResponse{Sequence: seq}, nil } +func (a Account) AuthRetroCompatibility(ctx context.Context, _ *authtypes.QueryLegacyAccount) (*authtypes.QueryLegacyAccountResponse, error) { + addr, err := a.addrCodec.BytesToString(accountstd.Whoami(ctx)) + if err != nil { + return nil, err + } + + accNumber, err := accountstd.QueryModule[*accountsv1.AccountNumberResponse](ctx, &accountsv1.AccountNumberRequest{Address: addr}) + if err != nil { + return nil, err + } + pk, err := a.loadPubKey(ctx) + if err != nil { + return nil, err + } + anyPk, err := gogotypes.NewAnyWithCacheWithValue(pk) + if err != nil { + return nil, err + } + + seq, err := a.Sequence.Peek(ctx) + if err != nil { + return nil, err + } + + baseAccount := &authtypes.BaseAccount{ + Address: addr, + PubKey: anyPk, + AccountNumber: accNumber.Number, + Sequence: seq, + } + + baseAccountAny, err := gogotypes.NewAnyWithCacheWithValue(baseAccount) + if err != nil { + return nil, err + } + + return &authtypes.QueryLegacyAccountResponse{ + Account: baseAccountAny, + Info: baseAccount, + }, nil +} + func (a Account) RegisterInitHandler(builder *accountstd.InitBuilder) { accountstd.RegisterInitHandler(builder, a.Init) } @@ -272,4 +311,5 @@ func (a Account) RegisterExecuteHandlers(builder *accountstd.ExecuteBuilder) { func (a Account) RegisterQueryHandlers(builder *accountstd.QueryBuilder) { accountstd.RegisterQueryHandler(builder, a.QuerySequence) + accountstd.RegisterQueryHandler(builder, a.AuthRetroCompatibility) } diff --git a/x/accounts/defaults/base/go.mod b/x/accounts/defaults/base/go.mod new file mode 100644 index 000000000000..2ac156c70cc5 --- /dev/null +++ b/x/accounts/defaults/base/go.mod @@ -0,0 +1,189 @@ +module cosmossdk.io/x/accounts/defaults/base + +go 1.23.1 + +require ( + cosmossdk.io/api v0.7.5 + cosmossdk.io/collections v0.4.0 + cosmossdk.io/core v1.0.0-alpha.3 + cosmossdk.io/x/accounts v0.0.0-20240913065641-0064ccbce64e + cosmossdk.io/x/tx v0.13.3 + github.com/cosmos/cosmos-sdk v0.53.0 + github.com/cosmos/gogoproto v1.7.0 + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 + github.com/stretchr/testify v1.9.0 + google.golang.org/protobuf v1.34.2 +) + +require ( + buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect + buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect + cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/depinject v1.0.0 // indirect + cosmossdk.io/errors v1.0.1 // indirect + cosmossdk.io/log v1.4.1 // indirect + cosmossdk.io/math v1.3.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect + cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect + cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect + cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect + filippo.io/edwards25519 v1.1.0 // indirect + github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect + github.com/99designs/keyring v1.2.2 // indirect + github.com/DataDog/datadog-go v4.8.3+incompatible // indirect + github.com/DataDog/zstd v1.5.5 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bgentry/speakeasy v0.2.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/cockroachdb/errors v1.11.3 // indirect + github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/pebble v1.1.2 // indirect + github.com/cockroachdb/redact v1.1.5 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/cometbft/cometbft v1.0.0-rc1.0.20240908111210-ab0be101882f // indirect + github.com/cometbft/cometbft-db v0.15.0 // indirect + github.com/cometbft/cometbft/api v1.0.0-rc.1 // indirect + github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect + github.com/cosmos/crypto v0.1.2 // indirect + github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/cosmos/gogogateway v1.2.0 // indirect + github.com/cosmos/iavl v1.3.0 // indirect + github.com/cosmos/ics23/go v0.11.0 // indirect + github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect + github.com/danieljoos/wincred v1.2.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/dgraph-io/badger/v4 v4.3.0 // indirect + github.com/dgraph-io/ristretto v0.1.2-0.20240116140435-c67e07994f91 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/dvsekhvalnov/jose2go v1.6.0 // indirect + github.com/emicklei/dot v1.6.2 // indirect + github.com/fatih/color v1.17.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/getsentry/sentry-go v0.27.0 // indirect + github.com/go-kit/kit v0.13.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/gogo/googleapis v1.4.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/btree v1.1.3 // indirect + github.com/google/flatbuffers v2.0.8+incompatible // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/orderedcode v0.0.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/handlers v1.5.2 // indirect + github.com/gorilla/mux v1.8.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-metrics v0.5.3 // indirect + github.com/hashicorp/go-plugin v1.6.1 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hashicorp/yamux v0.1.1 // indirect + github.com/hdevalence/ed25519consensus v0.2.0 // indirect + github.com/huandu/skiplist v1.2.0 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/linxGnu/grocksdb v1.9.3 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/minio/highwayhash v1.0.3 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mtibben/percent v0.2.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect + github.com/oklog/run v1.1.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/rs/cors v1.11.0 // indirect + github.com/rs/zerolog v1.33.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sasha-s/go-deadlock v0.3.5 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.7.0 // indirect + github.com/spf13/cobra v1.8.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.19.0 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/supranational/blst v0.3.13 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect + github.com/tendermint/go-amino v0.16.0 // indirect + github.com/tidwall/btree v1.7.0 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v0.14.3 // indirect + gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect + gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect + go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 // indirect + go.opencensus.io v0.24.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/term v0.24.0 // indirect + golang.org/x/text v0.18.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect + google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/grpc v1.66.2 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + gotest.tools/v3 v3.5.1 // indirect + pgregory.net/rapid v1.1.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect +) + +replace github.com/cosmos/cosmos-sdk => ../../../../. + +replace ( + cosmossdk.io/api => ../../../../api + cosmossdk.io/collections => ../../../../collections // TODO tag new collections ASAP + cosmossdk.io/core/testing => ../../../../core/testing + cosmossdk.io/store => ../../../../store + cosmossdk.io/x/accounts => ../../. + cosmossdk.io/x/accounts/defaults/multisig => ../multisig + cosmossdk.io/x/auth => ../../../auth + cosmossdk.io/x/bank => ../../../bank + cosmossdk.io/x/consensus => ../../../consensus + cosmossdk.io/x/distribution => ../../../distribution + cosmossdk.io/x/gov => ../../../gov + cosmossdk.io/x/mint => ../../../mint + cosmossdk.io/x/protocolpool => ../../../protocolpool + cosmossdk.io/x/slashing => ../../../slashing + cosmossdk.io/x/staking => ../../../staking + cosmossdk.io/x/tx => ../../../tx +) diff --git a/x/accounts/defaults/base/go.sum b/x/accounts/defaults/base/go.sum new file mode 100644 index 000000000000..a567e70aa1ee --- /dev/null +++ b/x/accounts/defaults/base/go.sum @@ -0,0 +1,695 @@ +buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 h1:90/4O5QkHb8EZdA2SAhueRzYw6u5ZHCPKtReFqshnTY= +buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2/go.mod h1:1+3gJj2NvZ1mTLAtHu+lMhOjGgQPiCKCeo+9MBww0Eo= +buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 h1:b7EEYTUHmWSBEyISHlHvXbJPqtKiHRuUignL1tsHnNQ= +buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= +cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= +cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= +cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= +cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= +cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= +cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= +cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= +github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0= +github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTBqhFkHUrPk= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= +github.com/DataDog/datadog-go v4.8.3+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= +github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/adlio/schema v1.3.6 h1:k1/zc2jNfeiZBA5aFTRy37jlBIuCkXCm0XmvpzCKI9I= +github.com/adlio/schema v1.3.6/go.mod h1:qkxwLgPBd1FgLRHYVCmQT/rrBr3JH38J9LjmVzWNudg= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE51E= +github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= +github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v1.1.2 h1:CUh2IPtR4swHlEj48Rhfzw6l/d0qA31fItcIszQVIsA= +github.com/cockroachdb/pebble v1.1.2/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/cometbft/cometbft v1.0.0-rc1.0.20240908111210-ab0be101882f h1:rPWKqyc+CeuddICqlqptf+3NPE8exbC9SOGuDPTEN3k= +github.com/cometbft/cometbft v1.0.0-rc1.0.20240908111210-ab0be101882f/go.mod h1:MqZ5E5jLU1JdP10FSRXhItpm+GdHMbW7Myv3UARLxqg= +github.com/cometbft/cometbft-db v0.15.0 h1:VLtsRt8udD4jHCyjvrsTBpgz83qne5hnL245AcPJVRk= +github.com/cometbft/cometbft-db v0.15.0/go.mod h1:EBrFs1GDRiTqrWXYi4v90Awf/gcdD5ExzdPbg4X8+mk= +github.com/cometbft/cometbft/api v1.0.0-rc.1 h1:GtdXwDGlqwHYs16A4egjwylfYOMYyEacLBrs3Zvpt7g= +github.com/cometbft/cometbft/api v1.0.0-rc.1/go.mod h1:NDFKiBBD8HJC6QQLAoUI99YhsiRZtg2+FJWfk6A6m6o= +github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= +github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= +github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 h1:V3WlarcZwlYYt3dUsStxm0FAFXVeEcvgwfmR6upxm5M= +github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22/go.mod h1:Z8IXcFJ9PqKK6BIsVOB3QXtkKoqUOp1vRvPT39kOXEA= +github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= +github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= +github.com/cosmos/crypto v0.1.2 h1:Yn500sPY+9sKVdhiPUSDtt8JOpBGMB515dOmla4zfls= +github.com/cosmos/crypto v0.1.2/go.mod h1:b6VWz3HczIpBaQPvI7KrbQeF3pXHh0al3T5e0uwMBQw= +github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= +github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= +github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= +github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= +github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= +github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= +github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= +github.com/cosmos/iavl v1.3.0 h1:Ezaxt8aPA3kbkhsfyqwenChGLQwHDAIif3tG9x1FMV8= +github.com/cosmos/iavl v1.3.0/go.mod h1:T6SfBcyhulVIY2G/ZtAtQm/QiJvsuhIos52V4dWYk88= +github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU= +github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0= +github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= +github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/danieljoos/wincred v1.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs= +github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/dgraph-io/badger/v4 v4.3.0 h1:lcsCE1/1qrRhqP+zYx6xDZb8n7U+QlwNicpc676Ub40= +github.com/dgraph-io/badger/v4 v4.3.0/go.mod h1:Sc0T595g8zqAQRDf44n+z3wG4BOqLwceaFntt8KPxUM= +github.com/dgraph-io/ristretto v0.1.2-0.20240116140435-c67e07994f91 h1:Pux6+xANi0I7RRo5E1gflI4EZ2yx3BGZ75JkAIvGEOA= +github.com/dgraph-io/ristretto v0.1.2-0.20240116140435-c67e07994f91/go.mod h1:swkazRqnUf1N62d0Nutz7KIj2UKqsm/H8tD0nBJAXqM= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY= +github.com/dvsekhvalnov/jose2go v1.6.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A= +github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= +github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/googleapis v1.4.1-0.20201022092350-68b0159b7869/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= +github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM= +github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= +github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= +github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-metrics v0.5.3 h1:M5uADWMOGCTUNU1YuC4hfknOeHNaX54LDm4oYSucoNE= +github.com/hashicorp/go-metrics v0.5.3/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= +github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI= +github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU= +github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= +github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= +github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= +github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= +github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8= +github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= +github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/linxGnu/grocksdb v1.9.3 h1:s1cbPcOd0cU2SKXRG1nEqCOWYAELQjdqg3RVI2MH9ik= +github.com/linxGnu/grocksdb v1.9.3/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q= +github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= +github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= +github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= +github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.28.1 h1:MijcGUbfYuznzK/5R4CPNoUP/9Xvuo20sXfEm6XxoTA= +github.com/onsi/gomega v1.28.1/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= +github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= +github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= +github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= +github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= +github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= +github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/supranational/blst v0.3.13 h1:AYeSxdOMacwu7FBmpfloBz5pbFXDmJL33RuwnKtmTjk= +github.com/supranational/blst v0.3.13/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= +github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= +github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= +github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= +github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= +github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= +github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b h1:CzigHMRySiX3drau9C6Q5CAbNIApmLdat5jPMqChvDA= +gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b/go.mod h1:/y/V339mxv2sZmYYR64O07VuCpdNZqCTwO8ZcouTMI8= +gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 h1:qwDnMxjkyLmAFgcfgTnfJrmYKWhHnci3GjDqcZp1M3Q= +gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02/go.mod h1:JTnUj0mpYiAsuZLmKjTx/ex3AtMowcCgnE7YNyCEP0I= +go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 h1:qxen9oVGzDdIRP6ejyAJc760RwW4SnVDiTYTzwnXuxo= +go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5/go.mod h1:eW0HG9/oHQhvRCvb1/pIXW4cOvtDqeQK+XSi3TnwaXY= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg= +golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= +google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= +google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= +pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/x/accounts/defaults/lockup/go.mod b/x/accounts/defaults/lockup/go.mod index e191695a75c2..f9d9f3f07cde 100644 --- a/x/accounts/defaults/lockup/go.mod +++ b/x/accounts/defaults/lockup/go.mod @@ -4,7 +4,7 @@ go 1.23.1 require ( cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/x/accounts v0.0.0-20240226161501-23359a0b6d91 cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 cosmossdk.io/x/distribution v0.0.0-00010101000000-000000000000 @@ -22,7 +22,7 @@ require ( cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect cosmossdk.io/x/tx v0.13.3 // indirect filippo.io/edwards25519 v1.1.0 // indirect @@ -96,7 +96,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -152,6 +152,7 @@ replace ( cosmossdk.io/core/testing => ../../../../core/testing cosmossdk.io/store => ../../../../store cosmossdk.io/x/accounts => ../../. + cosmossdk.io/x/accounts/defaults/multisig => ../multisig cosmossdk.io/x/bank => ../../../bank cosmossdk.io/x/consensus => ../../../consensus cosmossdk.io/x/distribution => ../../../distribution diff --git a/x/accounts/defaults/lockup/go.sum b/x/accounts/defaults/lockup/go.sum index 9e0736060c2e..5ed9fd12d490 100644 --- a/x/accounts/defaults/lockup/go.sum +++ b/x/accounts/defaults/lockup/go.sum @@ -4,8 +4,8 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +14,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/x/tx v0.13.3 h1:Ha4mNaHmxBc6RMun9aKuqul8yHiL78EKJQ8g23Zf73g= cosmossdk.io/x/tx v0.13.3/go.mod h1:I8xaHv0rhUdIvIdptKIqzYy27+n2+zBVaxO6fscFhys= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= @@ -349,8 +349,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/accounts/defaults/lockup/lockup.go b/x/accounts/defaults/lockup/lockup.go index c6abf92981ac..3ac17fea6133 100644 --- a/x/accounts/defaults/lockup/lockup.go +++ b/x/accounts/defaults/lockup/lockup.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "errors" - "fmt" "maps" "slices" "time" @@ -399,31 +398,22 @@ func (bva *BaseLockup) checkSender(ctx context.Context, sender string) error { } func sendMessage(ctx context.Context, msg proto.Message) ([]*codectypes.Any, error) { - response, err := accountstd.ExecModule(ctx, msg) + asAny, err := accountstd.PackAny(msg) if err != nil { return nil, err } - respAny, err := accountstd.PackAny(response) - if err != nil { - return nil, err - } - - return []*codectypes.Any{respAny}, nil + return accountstd.ExecModuleAnys(ctx, []*codectypes.Any{asAny}) } func getStakingDenom(ctx context.Context) (string, error) { // Query account balance for the sent denom - resp, err := accountstd.QueryModule(ctx, &stakingtypes.QueryParamsRequest{}) + resp, err := accountstd.QueryModule[*stakingtypes.QueryParamsResponse](ctx, &stakingtypes.QueryParamsRequest{}) if err != nil { return "", err } - res, ok := resp.(*stakingtypes.QueryParamsResponse) - if !ok { - return "", fmt.Errorf("unexpected response type: %T", resp) - } - return res.Params.BondDenom, nil + return resp.Params.BondDenom, nil } // TrackDelegation tracks a delegation amount for any given lockup account type @@ -548,17 +538,12 @@ func (bva *BaseLockup) TrackUndelegation(ctx context.Context, amount sdk.Coins) func (bva BaseLockup) getBalance(ctx context.Context, sender, denom string) (*sdk.Coin, error) { // Query account balance for the sent denom - resp, err := accountstd.QueryModule(ctx, &banktypes.QueryBalanceRequest{Address: sender, Denom: denom}) + resp, err := accountstd.QueryModule[*banktypes.QueryBalanceResponse](ctx, &banktypes.QueryBalanceRequest{Address: sender, Denom: denom}) if err != nil { return nil, err } - res, ok := resp.(*banktypes.QueryBalanceResponse) - if !ok { - return nil, fmt.Errorf("unexpected response type: %T", resp) - } - - return res.Balance, nil + return resp.Balance, nil } func (bva BaseLockup) checkTokensSendable(ctx context.Context, sender string, amount, lockedCoins sdk.Coins) error { diff --git a/x/accounts/defaults/lockup/lockup_test.go b/x/accounts/defaults/lockup/lockup_test.go index 67f3cadfbdf4..31c3fda141a3 100644 --- a/x/accounts/defaults/lockup/lockup_test.go +++ b/x/accounts/defaults/lockup/lockup_test.go @@ -53,7 +53,6 @@ func TestInitLockupAccount(t *testing.T) { } for _, test := range testcases { - test := test _, err := baseLockup.Init(ctx, &test.msg) if test.expErr != nil { require.Equal(t, test.expErr, err) diff --git a/x/accounts/defaults/multisig/go.mod b/x/accounts/defaults/multisig/go.mod index a6a2b99bb3c3..6908b2e0eb21 100644 --- a/x/accounts/defaults/multisig/go.mod +++ b/x/accounts/defaults/multisig/go.mod @@ -4,7 +4,7 @@ go 1.23.1 require ( cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/math v1.3.0 cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 @@ -23,7 +23,7 @@ require ( cosmossdk.io/depinject v1.0.0 // indirect cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/log v1.4.1 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -118,7 +118,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -177,6 +177,7 @@ replace ( cosmossdk.io/x/accounts => ../../. cosmossdk.io/x/bank => ../../../bank cosmossdk.io/x/consensus => ../../../consensus + cosmossdk.io/x/distribution => ../../../distribution cosmossdk.io/x/gov => ../../../gov cosmossdk.io/x/mint => ../../../mint cosmossdk.io/x/protocolpool => ../../../protocolpool diff --git a/x/accounts/defaults/multisig/go.sum b/x/accounts/defaults/multisig/go.sum index af04341f3bfc..a567e70aa1ee 100644 --- a/x/accounts/defaults/multisig/go.sum +++ b/x/accounts/defaults/multisig/go.sum @@ -4,8 +4,8 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +14,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -400,8 +400,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/accounts/go.mod b/x/accounts/go.mod index 338cb3cc8a18..1d8990803eec 100644 --- a/x/accounts/go.mod +++ b/x/accounts/go.mod @@ -5,15 +5,15 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/depinject v1.0.0 + cosmossdk.io/x/accounts/defaults/base v0.0.0-00010101000000-000000000000 cosmossdk.io/x/accounts/defaults/multisig v0.0.0-00010101000000-000000000000 cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 cosmossdk.io/x/tx v0.13.3 github.com/cosmos/cosmos-sdk v0.53.0 github.com/cosmos/gogoproto v1.7.0 - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 google.golang.org/grpc v1.66.2 @@ -22,6 +22,7 @@ require ( require ( github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/google/uuid v1.6.0 // indirect ) @@ -31,7 +32,7 @@ require ( cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/log v1.4.1 // indirect cosmossdk.io/math v1.3.0 - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 cosmossdk.io/x/distribution v0.0.0-00010101000000-000000000000 // indirect @@ -126,7 +127,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -181,6 +182,7 @@ replace ( cosmossdk.io/collections => ../../collections cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store + cosmossdk.io/x/accounts/defaults/base => ./defaults/base // REMOVE this when cosmossdk.io/x/accounts/defaults/lockup => ./defaults/lockup cosmossdk.io/x/accounts/defaults/multisig => ./defaults/multisig cosmossdk.io/x/bank => ../bank diff --git a/x/accounts/go.sum b/x/accounts/go.sum index cd6b45de5cf6..1f881f41bb27 100644 --- a/x/accounts/go.sum +++ b/x/accounts/go.sum @@ -4,8 +4,8 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +14,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -400,8 +400,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/auth/CHANGELOG.md b/x/auth/CHANGELOG.md index 6155638ff2e9..51a1eb6ea034 100644 --- a/x/auth/CHANGELOG.md +++ b/x/auth/CHANGELOG.md @@ -60,6 +60,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [#18817](https://github.com/cosmos/cosmos-sdk/pull/18817) SigVerification, GasConsumption, IncreaseSequence ante decorators have all been joined into one SigVerification decorator. Gas consumption during TX validation flow has reduced. * [#19093](https://github.com/cosmos/cosmos-sdk/pull/19093) SetPubKeyDecorator was merged into SigVerification, gas consumption is almost halved for a simple tx. * [#19535](https://github.com/cosmos/cosmos-sdk/pull/19535) Remove vesting account creation when the chain is running. The accounts module is required for creating [#vesting accounts](../accounts/defaults/lockup/README.md) on a running chain. +* [#21688](https://github.com/cosmos/cosmos-sdk/pull/21688) Allow x/accounts to be queriable from the `AccountInfo` and `Account` gRPC endpoints ### Bug Fixes diff --git a/x/auth/ante/basic_test.go b/x/auth/ante/basic_test.go index 389096d3d7c6..fd0dc29c1f0c 100644 --- a/x/auth/ante/basic_test.go +++ b/x/auth/ante/basic_test.go @@ -221,8 +221,6 @@ func TestTxHeightTimeoutDecorator(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder() diff --git a/x/auth/client/tx_test.go b/x/auth/client/tx_test.go index 18ee2cd5a4d2..4c35286d7427 100644 --- a/x/auth/client/tx_test.go +++ b/x/auth/client/tx_test.go @@ -172,7 +172,6 @@ func TestBatchScanner_Scan(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { scanner, i := authclient.NewBatchScanner(clientCtx.TxConfig, strings.NewReader(tt.batch)), 0 for scanner.Scan() { diff --git a/x/auth/keeper/grpc_query.go b/x/auth/keeper/grpc_query.go index 402eb6b0a149..f64de8f0a20e 100644 --- a/x/auth/keeper/grpc_query.go +++ b/x/auth/keeper/grpc_query.go @@ -80,7 +80,11 @@ func (s queryServer) Account(ctx context.Context, req *types.QueryAccountRequest } account := s.k.GetAccount(ctx, addr) if account == nil { - return nil, status.Errorf(codes.NotFound, "account %s not found", req.Address) + xAccount, err := s.getFromXAccounts(ctx, addr) + if err != nil { + return nil, status.Errorf(codes.NotFound, "account %s not found", req.Address) + } + return &types.QueryAccountResponse{Account: xAccount.Account}, nil } any, err := codectypes.NewAnyWithValue(account) @@ -224,7 +228,13 @@ func (s queryServer) AccountInfo(ctx context.Context, req *types.QueryAccountInf account := s.k.GetAccount(ctx, addr) if account == nil { - return nil, status.Errorf(codes.NotFound, "account %s not found", req.Address) + xAccount, err := s.getFromXAccounts(ctx, addr) + // account info is nil it means that the account can be encapsulated into a + // legacy account representation but not a base account one. + if err != nil || xAccount.Info == nil { + return nil, status.Errorf(codes.NotFound, "account %s not found", req.Address) + } + return &types.QueryAccountInfoResponse{Info: xAccount.Info}, nil } // if there is no public key, avoid serializing the nil value @@ -246,3 +256,26 @@ func (s queryServer) AccountInfo(ctx context.Context, req *types.QueryAccountInf }, }, nil } + +var ( + errNotXAccount = errors.New("not an x/account") + errInvalidLegacyAccountImpl = errors.New("invalid legacy account implementation") +) + +func (s queryServer) getFromXAccounts(ctx context.Context, address []byte) (*types.QueryLegacyAccountResponse, error) { + if !s.k.AccountsModKeeper.IsAccountsModuleAccount(ctx, address) { + return nil, errNotXAccount + } + + // attempt to check if it can be queried for a legacy account representation. + resp, err := s.k.AccountsModKeeper.Query(ctx, address, &types.QueryLegacyAccount{}) + if err != nil { + return nil, err + } + + typedResp, ok := resp.(*types.QueryLegacyAccountResponse) + if !ok { + return nil, errInvalidLegacyAccountImpl + } + return typedResp, nil +} diff --git a/x/auth/keeper/grpc_query_test.go b/x/auth/keeper/grpc_query_test.go index 82e9cfe573fc..6f5a8700779e 100644 --- a/x/auth/keeper/grpc_query_test.go +++ b/x/auth/keeper/grpc_query_test.go @@ -8,6 +8,7 @@ import ( "sort" "github.com/cosmos/gogoproto/proto" + "github.com/golang/mock/gomock" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" @@ -135,6 +136,7 @@ func (suite *KeeperTestSuite) TestGRPCQueryAccount() { for _, tc := range testCases { suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { suite.SetupTest() // reset + suite.acctsModKeeper.EXPECT().IsAccountsModuleAccount(gomock.Any(), gomock.Any()).Return(false).AnyTimes() tc.malleate() res, err := suite.queryClient.Account(suite.ctx, req) diff --git a/x/auth/keeper/msg_server_test.go b/x/auth/keeper/msg_server_test.go index f65334ea5f1c..3e7a65cce451 100644 --- a/x/auth/keeper/msg_server_test.go +++ b/x/auth/keeper/msg_server_test.go @@ -120,7 +120,6 @@ func (s *KeeperTestSuite) TestUpdateParams() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { _, err := s.msgServer.UpdateParams(s.ctx, tc.req) if tc.expectErr { @@ -190,7 +189,6 @@ func (s *KeeperTestSuite) TestNonAtomicExec() { }).AnyTimes() for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { _, err := s.msgServer.NonAtomicExec(s.ctx, tc.req) if tc.expectErr { diff --git a/x/auth/migrations/legacytx/stdtx_test.go b/x/auth/migrations/legacytx/stdtx_test.go index cdb28e978b2b..83909d45d6ec 100644 --- a/x/auth/migrations/legacytx/stdtx_test.go +++ b/x/auth/migrations/legacytx/stdtx_test.go @@ -90,7 +90,6 @@ func TestStdSignBytes(t *testing.T) { FileResolver: proto.HybridResolver, }) for i, tc := range tests { - tc := tc t.Run(tc.name, func(t *testing.T) { anyMsgs := make([]*anypb.Any, len(tc.args.msgs)) for j, msg := range tc.args.msgs { diff --git a/x/auth/module.go b/x/auth/module.go index 095304de78eb..b959fcde5408 100644 --- a/x/auth/module.go +++ b/x/auth/module.go @@ -15,6 +15,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simsx" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" @@ -188,17 +189,12 @@ func (am AppModule) GenerateGenesisState(simState *module.SimulationState) { simulation.RandomizedGenState(simState, am.randGenAccountsFn) } -// ProposalMsgs returns msgs used for governance proposals for simulations. -func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { - return simulation.ProposalMsgs() +// ProposalMsgsX returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_update_params", 100), simulation.MsgUpdateParamsFactory()) } // RegisterStoreDecoder registers a decoder for auth module's types func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[types.StoreKey] = simtypes.NewStoreDecoderFuncFromCollectionsSchema(am.accountKeeper.Schema) } - -// WeightedOperations doesn't return any auth module operation. -func (AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { - return nil -} diff --git a/x/auth/proto/cosmos/auth/v1beta1/accounts.proto b/x/auth/proto/cosmos/auth/v1beta1/accounts.proto new file mode 100644 index 000000000000..2e15375c39e4 --- /dev/null +++ b/x/auth/proto/cosmos/auth/v1beta1/accounts.proto @@ -0,0 +1,27 @@ +syntax = "proto3"; +package cosmos.auth.v1beta1; + +import "google/protobuf/any.proto"; + +import "cosmos/auth/v1beta1/auth.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/auth/types"; + +// QueryLegacyAccount defines a query that can be implemented by an x/account +// to return an auth understandable representation of an account. +// This query is only used for accounts retro-compatibility at gRPC +// level, the state machine must not make any assumptions around this. +message QueryLegacyAccount {} + +// QueryLegacyAccountResponse defines the response type of the +// `QueryLegacyAccount` query. +message QueryLegacyAccountResponse { + // account represents the google.Protobuf.Any wrapped account + // the type wrapped by the any does not need to comply with the + // sdk.AccountI interface. + google.protobuf.Any account = 1; + // info represents the account as a BaseAccount, this can return + // nil if the account cannot be represented as a BaseAccount. + // This is used in the gRPC QueryAccountInfo method. + BaseAccount base = 2; +} \ No newline at end of file diff --git a/x/auth/simulation/genesis.go b/x/auth/simulation/genesis.go index c6984cc355e8..7c18882fd325 100644 --- a/x/auth/simulation/genesis.go +++ b/x/auth/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" sdk "github.com/cosmos/cosmos-sdk/types" @@ -113,10 +111,5 @@ func RandomizedGenState(simState *module.SimulationState, randGenAccountsFn type authGenesis := types.NewGenesisState(params, genesisAccs) - bz, err := json.MarshalIndent(&authGenesis.Params, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated auth parameters:\n%s\n", bz) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(authGenesis) } diff --git a/x/auth/simulation/msg_factory.go b/x/auth/simulation/msg_factory.go new file mode 100644 index 000000000000..83bcca3029d4 --- /dev/null +++ b/x/auth/simulation/msg_factory.go @@ -0,0 +1,25 @@ +package simulation + +import ( + "context" + + "github.com/cosmos/cosmos-sdk/simsx" + "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +func MsgUpdateParamsFactory() simsx.SimMsgFactoryFn[*types.MsgUpdateParams] { + return func(_ context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgUpdateParams) { + r := testData.Rand() + params := types.DefaultParams() + params.MaxMemoCharacters = r.Uint64InRange(1, 1000) + params.TxSigLimit = r.Uint64InRange(1, 1000) + params.TxSizeCostPerByte = r.Uint64InRange(1, 1000) + params.SigVerifyCostED25519 = r.Uint64InRange(1, 1000) + params.SigVerifyCostSecp256k1 = r.Uint64InRange(1, 1000) + + return nil, &types.MsgUpdateParams{ + Authority: testData.ModuleAccountAddress(reporter, "gov"), + Params: params, + } + } +} diff --git a/x/auth/simulation/proposals.go b/x/auth/simulation/proposals.go deleted file mode 100644 index 930d9153fd88..000000000000 --- a/x/auth/simulation/proposals.go +++ /dev/null @@ -1,50 +0,0 @@ -package simulation - -import ( - "context" - "math/rand" - - coreaddress "cosmossdk.io/core/address" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/auth/types" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - DefaultWeightMsgUpdateParams int = 100 - - OpWeightMsgUpdateParams = "op_weight_msg_update_params" -) - -// ProposalMsgs defines the module weighted proposals' contents -func ProposalMsgs() []simtypes.WeightedProposalMsg { - return []simtypes.WeightedProposalMsg{ - simulation.NewWeightedProposalMsgX( - OpWeightMsgUpdateParams, - DefaultWeightMsgUpdateParams, - SimulateMsgUpdateParams, - ), - } -} - -// SimulateMsgUpdateParams returns a random MsgUpdateParams -func SimulateMsgUpdateParams(_ context.Context, r *rand.Rand, _ []simtypes.Account, _ coreaddress.Codec) (sdk.Msg, error) { - // use the default gov module account address as authority - var authority sdk.AccAddress = address.Module("gov") - - params := types.DefaultParams() - params.MaxMemoCharacters = uint64(simtypes.RandIntBetween(r, 1, 1000)) - params.TxSigLimit = uint64(simtypes.RandIntBetween(r, 1, 1000)) - params.TxSizeCostPerByte = uint64(simtypes.RandIntBetween(r, 1, 1000)) - params.SigVerifyCostED25519 = uint64(simtypes.RandIntBetween(r, 1, 1000)) - params.SigVerifyCostSecp256k1 = uint64(simtypes.RandIntBetween(r, 1, 1000)) - - return &types.MsgUpdateParams{ - Authority: authority.String(), - Params: params, - }, nil -} diff --git a/x/auth/simulation/proposals_test.go b/x/auth/simulation/proposals_test.go deleted file mode 100644 index f43e105d3056..000000000000 --- a/x/auth/simulation/proposals_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package simulation_test - -import ( - "math/rand" - "testing" - - "gotest.tools/v3/assert" - - codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/auth/simulation" - "github.com/cosmos/cosmos-sdk/x/auth/types" -) - -func TestProposalMsgs(t *testing.T) { - // initialize parameters - s := rand.NewSource(1) - r := rand.New(s) - - accounts := simtypes.RandomAccounts(r, 3) - - // execute ProposalMsgs function - weightedProposalMsgs := simulation.ProposalMsgs() - assert.Assert(t, len(weightedProposalMsgs) == 1) - - w0 := weightedProposalMsgs[0] - - // tests w0 interface: - assert.Equal(t, simulation.OpWeightMsgUpdateParams, w0.AppParamsKey()) - assert.Equal(t, simulation.DefaultWeightMsgUpdateParams, w0.DefaultWeight()) - - msg, err := w0.MsgSimulatorFn()(sdk.Context{}, r, accounts, codectestutil.CodecOptions{}.GetAddressCodec()) - assert.NilError(t, err) - msgUpdateParams, ok := msg.(*types.MsgUpdateParams) - assert.Assert(t, ok) - - assert.Equal(t, sdk.AccAddress(address.Module("gov")).String(), msgUpdateParams.Authority) - assert.Equal(t, uint64(999), msgUpdateParams.Params.MaxMemoCharacters) - assert.Equal(t, uint64(905), msgUpdateParams.Params.TxSigLimit) - assert.Equal(t, uint64(151), msgUpdateParams.Params.TxSizeCostPerByte) - assert.Equal(t, uint64(213), msgUpdateParams.Params.SigVerifyCostED25519) - assert.Equal(t, uint64(539), msgUpdateParams.Params.SigVerifyCostSecp256k1) -} diff --git a/x/auth/testutil/expected_keepers_mocks.go b/x/auth/testutil/expected_keepers_mocks.go index 348a1740378a..f4e23bcbc06e 100644 --- a/x/auth/testutil/expected_keepers_mocks.go +++ b/x/auth/testutil/expected_keepers_mocks.go @@ -149,6 +149,21 @@ func (mr *MockAccountsModKeeperMockRecorder) NextAccountNumber(ctx interface{}) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NextAccountNumber", reflect.TypeOf((*MockAccountsModKeeper)(nil).NextAccountNumber), ctx) } +// Query mocks base method. +func (m *MockAccountsModKeeper) Query(ctx context.Context, accountAddr []byte, queryRequest transaction.Msg) (transaction.Msg, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Query", ctx, accountAddr, queryRequest) + ret0, _ := ret[0].(transaction.Msg) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Query indicates an expected call of Query. +func (mr *MockAccountsModKeeperMockRecorder) Query(ctx, accountAddr, queryRequest interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Query", reflect.TypeOf((*MockAccountsModKeeper)(nil).Query), ctx, accountAddr, queryRequest) +} + // SendModuleMessage mocks base method. func (m *MockAccountsModKeeper) SendModuleMessage(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) { m.ctrl.T.Helper() diff --git a/x/auth/tx/aux_test.go b/x/auth/tx/aux_test.go index f1e8dca0879b..9ac871bed501 100644 --- a/x/auth/tx/aux_test.go +++ b/x/auth/tx/aux_test.go @@ -100,7 +100,6 @@ func TestBuilderWithAux(t *testing.T) { {"happy case", func() {}, false}, } for _, tc := range testcases { - tc := tc t.Run(tc.name, func(t *testing.T) { txBuilder, txSig = makeTxBuilder(t) diff --git a/x/auth/tx/query.go b/x/auth/tx/query.go index c49ddfa25458..54af403316fb 100644 --- a/x/auth/tx/query.go +++ b/x/auth/tx/query.go @@ -114,8 +114,6 @@ func getBlocksForTxResults(clientCtx client.Context, resTxs []*coretypes.ResultT resBlocks := make(map[int64]*coretypes.ResultBlock) for _, resTx := range resTxs { - resTx := resTx - if _, ok := resBlocks[resTx.Height]; !ok { resBlock, err := node.Block(context.Background(), &resTx.Height) if err != nil { diff --git a/x/auth/types/account_test.go b/x/auth/types/account_test.go index b4fadfa391a7..f0cc88ae85fa 100644 --- a/x/auth/types/account_test.go +++ b/x/auth/types/account_test.go @@ -84,8 +84,6 @@ func TestGenesisAccountValidate(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { require.Equal(t, tt.expErr, tt.acc.Validate() != nil) }) @@ -151,7 +149,6 @@ func TestValidate(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { err := tt.acc.Validate() require.Equal(t, tt.expErr, err) diff --git a/x/auth/types/accounts.pb.go b/x/auth/types/accounts.pb.go new file mode 100644 index 000000000000..380a1e9195c9 --- /dev/null +++ b/x/auth/types/accounts.pb.go @@ -0,0 +1,523 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/auth/v1beta1/accounts.proto + +package types + +import ( + fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" + any "github.com/cosmos/gogoproto/types/any" + 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 + +// QueryLegacyAccount defines a query that can be implemented by an x/account +// to return an auth understandable representation of an account. +// This query is only used for accounts retro-compatibility at gRPC +// level, the state machine must not make any assumptions around this. +type QueryLegacyAccount struct { +} + +func (m *QueryLegacyAccount) Reset() { *m = QueryLegacyAccount{} } +func (m *QueryLegacyAccount) String() string { return proto.CompactTextString(m) } +func (*QueryLegacyAccount) ProtoMessage() {} +func (*QueryLegacyAccount) Descriptor() ([]byte, []int) { + return fileDescriptor_25696478f9b3e7f4, []int{0} +} +func (m *QueryLegacyAccount) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryLegacyAccount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryLegacyAccount.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 *QueryLegacyAccount) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryLegacyAccount.Merge(m, src) +} +func (m *QueryLegacyAccount) XXX_Size() int { + return m.Size() +} +func (m *QueryLegacyAccount) XXX_DiscardUnknown() { + xxx_messageInfo_QueryLegacyAccount.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryLegacyAccount proto.InternalMessageInfo + +// QueryLegacyAccountResponse defines the response type of the +// `QueryLegacyAccount` query. +type QueryLegacyAccountResponse struct { + // account represents the google.Protobuf.Any wrapped account + // the type wrapped by the any does not need to comply with the + // sdk.AccountI interface. + Account *any.Any `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"` + // info represents the account as a BaseAccount, this can return + // nil if the account cannot be represented as a base account. + // This is used in the gRPC QueryAccountInfo method. + Info *BaseAccount `protobuf:"bytes,2,opt,name=info,proto3" json:"info,omitempty"` +} + +func (m *QueryLegacyAccountResponse) Reset() { *m = QueryLegacyAccountResponse{} } +func (m *QueryLegacyAccountResponse) String() string { return proto.CompactTextString(m) } +func (*QueryLegacyAccountResponse) ProtoMessage() {} +func (*QueryLegacyAccountResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_25696478f9b3e7f4, []int{1} +} +func (m *QueryLegacyAccountResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryLegacyAccountResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryLegacyAccountResponse.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 *QueryLegacyAccountResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryLegacyAccountResponse.Merge(m, src) +} +func (m *QueryLegacyAccountResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryLegacyAccountResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryLegacyAccountResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryLegacyAccountResponse proto.InternalMessageInfo + +func (m *QueryLegacyAccountResponse) GetAccount() *any.Any { + if m != nil { + return m.Account + } + return nil +} + +func (m *QueryLegacyAccountResponse) GetInfo() *BaseAccount { + if m != nil { + return m.Info + } + return nil +} + +func init() { + proto.RegisterType((*QueryLegacyAccount)(nil), "cosmos.auth.v1beta1.QueryLegacyAccount") + proto.RegisterType((*QueryLegacyAccountResponse)(nil), "cosmos.auth.v1beta1.QueryLegacyAccountResponse") +} + +func init() { + proto.RegisterFile("cosmos/auth/v1beta1/accounts.proto", fileDescriptor_25696478f9b3e7f4) +} + +var fileDescriptor_25696478f9b3e7f4 = []byte{ + // 247 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0xcf, 0xb1, 0x4e, 0xc3, 0x30, + 0x10, 0x06, 0xe0, 0x18, 0x21, 0x90, 0xcc, 0x16, 0x3a, 0x94, 0x0c, 0x56, 0x95, 0x09, 0x06, 0xce, + 0x2a, 0xf0, 0x02, 0x2d, 0x2b, 0x0b, 0x1d, 0xd9, 0x1c, 0xe3, 0xa6, 0x15, 0xd4, 0x17, 0xf5, 0x6c, + 0x84, 0x57, 0x9e, 0x80, 0xc7, 0x62, 0xec, 0xc8, 0x88, 0x92, 0x17, 0x41, 0xb5, 0x93, 0xa9, 0x9d, + 0x2c, 0xd9, 0x9f, 0xef, 0xfe, 0x9f, 0x97, 0x1a, 0x69, 0x83, 0x24, 0x95, 0x77, 0x2b, 0xf9, 0x31, + 0xad, 0x8c, 0x53, 0x53, 0xa9, 0xb4, 0x46, 0x6f, 0x1d, 0x41, 0xb3, 0x45, 0x87, 0xf9, 0x65, 0x32, + 0xb0, 0x37, 0xd0, 0x9b, 0xe2, 0xaa, 0x46, 0xac, 0xdf, 0x8d, 0x8c, 0xa4, 0xf2, 0x4b, 0xa9, 0x6c, + 0x48, 0xbe, 0x10, 0x47, 0x67, 0xee, 0x3f, 0xc7, 0xf7, 0x72, 0xc4, 0xf3, 0x67, 0x6f, 0xb6, 0xe1, + 0xc9, 0xd4, 0x4a, 0x87, 0x59, 0x5a, 0x56, 0x7e, 0x31, 0x5e, 0x1c, 0x5e, 0x2f, 0x0c, 0x35, 0x68, + 0xc9, 0xe4, 0xc0, 0xcf, 0xfb, 0x58, 0x63, 0x36, 0x61, 0xd7, 0x17, 0x77, 0x23, 0x48, 0x09, 0x60, + 0x48, 0x00, 0x33, 0x1b, 0x16, 0x03, 0xca, 0x1f, 0xf8, 0xe9, 0xda, 0x2e, 0x71, 0x7c, 0x12, 0xf1, + 0x04, 0x8e, 0x74, 0x80, 0xb9, 0x22, 0x33, 0xec, 0x89, 0x7a, 0xfe, 0xf8, 0xd3, 0x0a, 0xb6, 0x6b, + 0x05, 0xfb, 0x6b, 0x05, 0xfb, 0xee, 0x44, 0xb6, 0xeb, 0x44, 0xf6, 0xdb, 0x89, 0xec, 0xe5, 0xa6, + 0x5e, 0xbb, 0x95, 0xaf, 0x40, 0xe3, 0x46, 0xf6, 0xfd, 0xd2, 0x71, 0x4b, 0xaf, 0x6f, 0xf2, 0x33, + 0x95, 0x75, 0xa1, 0x31, 0x54, 0x9d, 0xc5, 0x44, 0xf7, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xdf, + 0x0d, 0xc9, 0xcb, 0x5c, 0x01, 0x00, 0x00, +} + +func (m *QueryLegacyAccount) 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 *QueryLegacyAccount) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryLegacyAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryLegacyAccountResponse) 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 *QueryLegacyAccountResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryLegacyAccountResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Info != nil { + { + size, err := m.Info.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAccounts(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Account != nil { + { + size, err := m.Account.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAccounts(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintAccounts(dAtA []byte, offset int, v uint64) int { + offset -= sovAccounts(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryLegacyAccount) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryLegacyAccountResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Account != nil { + l = m.Account.Size() + n += 1 + l + sovAccounts(uint64(l)) + } + if m.Info != nil { + l = m.Info.Size() + n += 1 + l + sovAccounts(uint64(l)) + } + return n +} + +func sovAccounts(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozAccounts(x uint64) (n int) { + return sovAccounts(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryLegacyAccount) 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 ErrIntOverflowAccounts + } + 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: QueryLegacyAccount: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryLegacyAccount: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipAccounts(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAccounts + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryLegacyAccountResponse) 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 ErrIntOverflowAccounts + } + 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: QueryLegacyAccountResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryLegacyAccountResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Account", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAccounts + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAccounts + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAccounts + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Account == nil { + m.Account = &any.Any{} + } + if err := m.Account.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAccounts + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAccounts + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAccounts + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Info == nil { + m.Info = &BaseAccount{} + } + if err := m.Info.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAccounts(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAccounts + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipAccounts(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, ErrIntOverflowAccounts + } + 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, ErrIntOverflowAccounts + } + 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, ErrIntOverflowAccounts + } + 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, ErrInvalidLengthAccounts + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupAccounts + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthAccounts + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthAccounts = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowAccounts = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupAccounts = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/auth/types/expected_keepers.go b/x/auth/types/expected_keepers.go index 7fb82e89ed8a..8c7ca103858f 100644 --- a/x/auth/types/expected_keepers.go +++ b/x/auth/types/expected_keepers.go @@ -21,6 +21,13 @@ type AccountsModKeeper interface { IsAccountsModuleAccount(ctx context.Context, accountAddr []byte) bool NextAccountNumber(ctx context.Context) (accNum uint64, err error) + // Query is used to query an account + Query( + ctx context.Context, + accountAddr []byte, + queryRequest transaction.Msg, + ) (transaction.Msg, error) + // InitAccountNumberSeqUnsafe is use to set accounts module account number with value // of auth module current account number InitAccountNumberSeqUnsafe(ctx context.Context, currentAccNum uint64) error diff --git a/x/auth/types/params_test.go b/x/auth/types/params_test.go index 587778e1f3d9..9c776c5509e2 100644 --- a/x/auth/types/params_test.go +++ b/x/auth/types/params_test.go @@ -37,7 +37,6 @@ func TestParams_Validate(t *testing.T) { types.DefaultSigVerifyCostED25519, types.DefaultSigVerifyCostSecp256k1), errors.New("invalid tx size cost per byte: 0")}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { got := tt.params.Validate() if tt.wantErr == nil { diff --git a/x/auth/types/permissions_test.go b/x/auth/types/permissions_test.go index de5c25645769..78133007dac7 100644 --- a/x/auth/types/permissions_test.go +++ b/x/auth/types/permissions_test.go @@ -41,7 +41,6 @@ func TestValidatePermissions(t *testing.T) { } for i, tc := range cases { - i, tc := i, tc t.Run(tc.name, func(t *testing.T) { err := validatePermissions(tc.permissions...) if tc.expectPass { diff --git a/x/auth/vesting/testutil/expected_keepers_mocks.go b/x/auth/vesting/testutil/expected_keepers_mocks.go index 7612d81e200b..1df8f8ebbf2b 100644 --- a/x/auth/vesting/testutil/expected_keepers_mocks.go +++ b/x/auth/vesting/testutil/expected_keepers_mocks.go @@ -8,7 +8,6 @@ import ( context "context" reflect "reflect" - transaction "cosmossdk.io/core/transaction" types "github.com/cosmos/cosmos-sdk/types" gomock "github.com/golang/mock/gomock" ) @@ -82,84 +81,3 @@ func (mr *MockBankKeeperMockRecorder) SendCoins(ctx, fromAddr, toAddr, amt inter mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoins", reflect.TypeOf((*MockBankKeeper)(nil).SendCoins), ctx, fromAddr, toAddr, amt) } - -// MockAccountsModKeeper is a mock of AccountsModKeeper interface. -type MockAccountsModKeeper struct { - ctrl *gomock.Controller - recorder *MockAccountsModKeeperMockRecorder -} - -// MockAccountsModKeeperMockRecorder is the mock recorder for MockAccountsModKeeper. -type MockAccountsModKeeperMockRecorder struct { - mock *MockAccountsModKeeper -} - -// NewMockAccountsModKeeper creates a new mock instance. -func NewMockAccountsModKeeper(ctrl *gomock.Controller) *MockAccountsModKeeper { - mock := &MockAccountsModKeeper{ctrl: ctrl} - mock.recorder = &MockAccountsModKeeperMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockAccountsModKeeper) EXPECT() *MockAccountsModKeeperMockRecorder { - return m.recorder -} - -// InitAccountNumberSeqUnsafe mocks base method. -func (m *MockAccountsModKeeper) InitAccountNumberSeqUnsafe(ctx context.Context, currentAccNum uint64) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "InitAccountNumberSeqUnsafe", ctx, currentAccNum) - ret0, _ := ret[0].(error) - return ret0 -} - -// InitAccountNumberSeqUnsafe indicates an expected call of InitAccountNumberSeqUnsafe. -func (mr *MockAccountsModKeeperMockRecorder) InitAccountNumberSeqUnsafe(ctx, currentAccNum interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InitAccountNumberSeqUnsafe", reflect.TypeOf((*MockAccountsModKeeper)(nil).InitAccountNumberSeqUnsafe), ctx, currentAccNum) -} - -// IsAccountsModuleAccount mocks base method. -func (m *MockAccountsModKeeper) IsAccountsModuleAccount(ctx context.Context, accountAddr []byte) bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsAccountsModuleAccount", ctx, accountAddr) - ret0, _ := ret[0].(bool) - return ret0 -} - -// IsAccountsModuleAccount indicates an expected call of IsAccountsModuleAccount. -func (mr *MockAccountsModKeeperMockRecorder) IsAccountsModuleAccount(ctx, accountAddr interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsAccountsModuleAccount", reflect.TypeOf((*MockAccountsModKeeper)(nil).IsAccountsModuleAccount), ctx, accountAddr) -} - -// NextAccountNumber mocks base method. -func (m *MockAccountsModKeeper) NextAccountNumber(ctx context.Context) (uint64, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NextAccountNumber", ctx) - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// NextAccountNumber indicates an expected call of NextAccountNumber. -func (mr *MockAccountsModKeeperMockRecorder) NextAccountNumber(ctx interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NextAccountNumber", reflect.TypeOf((*MockAccountsModKeeper)(nil).NextAccountNumber), ctx) -} - -// SendModuleMessage mocks base method. -func (m *MockAccountsModKeeper) SendModuleMessage(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SendModuleMessage", ctx, sender, msg) - ret0, _ := ret[0].(transaction.Msg) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SendModuleMessage indicates an expected call of SendModuleMessage. -func (mr *MockAccountsModKeeperMockRecorder) SendModuleMessage(ctx, sender, msg interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendModuleMessage", reflect.TypeOf((*MockAccountsModKeeper)(nil).SendModuleMessage), ctx, sender, msg) -} diff --git a/x/auth/vesting/types/expected_keepers.go b/x/auth/vesting/types/expected_keepers.go index 3d8815385d10..6c4feaf4d20c 100644 --- a/x/auth/vesting/types/expected_keepers.go +++ b/x/auth/vesting/types/expected_keepers.go @@ -4,7 +4,6 @@ import ( "context" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth/types" ) // BankKeeper defines the expected interface contract the vesting module requires @@ -14,7 +13,3 @@ type BankKeeper interface { SendCoins(ctx context.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error BlockedAddr(addr sdk.AccAddress) bool } - -type AccountsModKeeper interface { - types.AccountsModKeeper -} diff --git a/x/auth/vesting/types/vesting_account_test.go b/x/auth/vesting/types/vesting_account_test.go index 54330978d127..f4d3aa044456 100644 --- a/x/auth/vesting/types/vesting_account_test.go +++ b/x/auth/vesting/types/vesting_account_test.go @@ -21,9 +21,9 @@ import ( moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec" "github.com/cosmos/cosmos-sdk/x/auth/keeper" + authtestutil "github.com/cosmos/cosmos-sdk/x/auth/testutil" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/auth/vesting" - vestingtestutil "github.com/cosmos/cosmos-sdk/x/auth/vesting/testutil" "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" ) @@ -50,7 +50,6 @@ func (s *VestingAccountTestSuite) SetupTest() { // gomock initializations ctrl := gomock.NewController(&testing.T{}) - acctsModKeeper := vestingtestutil.NewMockAccountsModKeeper(ctrl) maccPerms := map[string][]string{ "fee_collector": nil, @@ -65,7 +64,7 @@ func (s *VestingAccountTestSuite) SetupTest() { env, encCfg.Codec, authtypes.ProtoBaseAccount, - acctsModKeeper, + authtestutil.NewMockAccountsModKeeper(ctrl), maccPerms, authcodec.NewBech32Codec("cosmos"), "cosmos", @@ -917,8 +916,6 @@ func TestGenesisAccountValidate(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { require.Equal(t, tt.expErr, tt.acc.Validate() != nil) }) diff --git a/x/authz/authorization_grant_test.go b/x/authz/authorization_grant_test.go index 76d50f6c2dfc..7b048d3f2413 100644 --- a/x/authz/authorization_grant_test.go +++ b/x/authz/authorization_grant_test.go @@ -35,7 +35,6 @@ func TestNewGrant(t *testing.T) { } for _, tc := range tcs { - tc := tc t.Run(tc.title, func(t *testing.T) { _, err := NewGrant(tc.blockTime, tc.a, tc.expire) expecError(require.New(t), tc.err, err) @@ -59,7 +58,6 @@ func TestValidateBasic(t *testing.T) { } for _, tc := range tcs { - tc := tc t.Run(tc.title, func(t *testing.T) { grant := Grant{ Authorization: tc.authorization, diff --git a/x/authz/go.mod b/x/authz/go.mod index 6438c2e98c00..5c2fe38c31e1 100644 --- a/x/authz/go.mod +++ b/x/authz/go.mod @@ -4,7 +4,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 @@ -30,7 +30,7 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/collections v0.4.0 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.2 // indirect @@ -118,7 +118,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/x/authz/go.sum b/x/authz/go.sum index cd6b45de5cf6..1f881f41bb27 100644 --- a/x/authz/go.sum +++ b/x/authz/go.sum @@ -4,8 +4,8 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +14,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -400,8 +400,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/authz/keeper/grpc_query_test.go b/x/authz/keeper/grpc_query_test.go index 6cb51dbae0f7..b8d5042a96c8 100644 --- a/x/authz/keeper/grpc_query_test.go +++ b/x/authz/keeper/grpc_query_test.go @@ -192,7 +192,6 @@ func (suite *TestSuite) TestGRPCQueryGranterGrants() { } for _, tc := range testCases { - tc := tc suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { tc.preRun() result, err := queryClient.GranterGrants(gocontext.Background(), &tc.request) @@ -275,8 +274,6 @@ func (suite *TestSuite) TestGRPCQueryGranteeGrants() { } for _, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { tc.preRun() result, err := queryClient.GranteeGrants(gocontext.Background(), &tc.request) diff --git a/x/authz/module/depinject.go b/x/authz/module/depinject.go index 849471f8fa27..911bca8c1daa 100644 --- a/x/authz/module/depinject.go +++ b/x/authz/module/depinject.go @@ -29,7 +29,6 @@ type ModuleInputs struct { Cdc codec.Codec AccountKeeper authz.AccountKeeper - BankKeeper authz.BankKeeper Registry cdctypes.InterfaceRegistry Environment appmodule.Environment } @@ -43,6 +42,6 @@ type ModuleOutputs struct { func ProvideModule(in ModuleInputs) ModuleOutputs { k := keeper.NewKeeper(in.Environment, in.Cdc, in.AccountKeeper) - m := NewAppModule(in.Cdc, k, in.AccountKeeper, in.BankKeeper, in.Registry) + m := NewAppModule(in.Cdc, k, in.Registry) return ModuleOutputs{AuthzKeeper: k, Module: m} } diff --git a/x/authz/module/module.go b/x/authz/module/module.go index 1acb5727b2e8..d25ab35eba88 100644 --- a/x/authz/module/module.go +++ b/x/authz/module/module.go @@ -20,6 +20,7 @@ import ( sdkclient "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/simsx" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) @@ -40,27 +41,21 @@ var ( // AppModule implements the sdk.AppModule interface type AppModule struct { - cdc codec.Codec - keeper keeper.Keeper - accountKeeper authz.AccountKeeper - bankKeeper authz.BankKeeper - registry cdctypes.InterfaceRegistry + cdc codec.Codec + keeper keeper.Keeper + registry cdctypes.InterfaceRegistry } // NewAppModule creates a new AppModule object func NewAppModule( cdc codec.Codec, keeper keeper.Keeper, - ak authz.AccountKeeper, - bk authz.BankKeeper, registry cdctypes.InterfaceRegistry, ) AppModule { return AppModule{ - cdc: cdc, - keeper: keeper, - accountKeeper: ak, - bankKeeper: bk, - registry: registry, + cdc: cdc, + keeper: keeper, + registry: registry, } } @@ -166,11 +161,8 @@ func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[keeper.StoreKey] = simulation.NewDecodeStore(am.cdc) } -// WeightedOperations returns the all the gov module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - am.registry, - simState.AppParams, simState.Cdc, simState.TxConfig, - am.accountKeeper, am.bankKeeper, am.keeper, - ) +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_grant", 100), simulation.MsgGrantFactory()) + reg.Add(weights.Get("msg_revoke", 90), simulation.MsgRevokeFactory(am.keeper)) + reg.Add(weights.Get("msg_exec", 90), simulation.MsgExecFactory(am.keeper)) } diff --git a/x/authz/simulation/decoder_test.go b/x/authz/simulation/decoder_test.go index ff14fd76e316..94f87b729cf4 100644 --- a/x/authz/simulation/decoder_test.go +++ b/x/authz/simulation/decoder_test.go @@ -48,7 +48,6 @@ func TestDecodeStore(t *testing.T) { } for i, tt := range tests { - i, tt := i, tt t.Run(tt.name, func(t *testing.T) { if tt.expectErr { require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) diff --git a/x/authz/simulation/genesis.go b/x/authz/simulation/genesis.go index 59b2d299a46c..de650064407b 100644 --- a/x/authz/simulation/genesis.go +++ b/x/authz/simulation/genesis.go @@ -5,7 +5,6 @@ import ( "time" v1 "cosmossdk.io/api/cosmos/gov/v1" - "cosmossdk.io/core/address" sdkmath "cosmossdk.io/math" "cosmossdk.io/x/authz" banktypes "cosmossdk.io/x/bank/types" @@ -16,23 +15,31 @@ import ( simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) +// RandomizedGenState generates a random GenesisState for authz. +func RandomizedGenState(simState *module.SimulationState) { + var grants []authz.GrantAuthorization + simState.AppParams.GetOrGenerate("authz", &grants, simState.Rand, func(r *rand.Rand) { + grants = genGrant(r, simState.Accounts, simState.GenTimestamp) + }) + + authzGrantsGenesis := authz.NewGenesisState(grants) + + simState.GenState[authz.ModuleName] = simState.Cdc.MustMarshalJSON(authzGrantsGenesis) +} + // genGrant returns a slice of authorization grants. -func genGrant(r *rand.Rand, accounts []simtypes.Account, genT time.Time, cdc address.Codec) []authz.GrantAuthorization { +func genGrant(r *rand.Rand, accounts []simtypes.Account, genT time.Time) []authz.GrantAuthorization { authorizations := make([]authz.GrantAuthorization, len(accounts)-1) for i := 0; i < len(accounts)-1; i++ { - granter := accounts[i] - grantee := accounts[i+1] var expiration *time.Time if i%3 != 0 { // generate some grants with no expire time e := genT.AddDate(1, 0, 0) expiration = &e } - granterAddr, _ := cdc.BytesToString(granter.Address) - granteeAddr, _ := cdc.BytesToString(grantee.Address) authorizations[i] = authz.GrantAuthorization{ - Granter: granterAddr, - Grantee: granteeAddr, - Authorization: generateRandomGrant(r, cdc), + Granter: accounts[i].AddressBech32, + Grantee: accounts[i+1].AddressBech32, + Authorization: generateRandomGrant(r), Expiration: expiration, } } @@ -40,32 +47,17 @@ func genGrant(r *rand.Rand, accounts []simtypes.Account, genT time.Time, cdc add return authorizations } -func generateRandomGrant(r *rand.Rand, addressCodec address.Codec) *codectypes.Any { - authorizations := make([]*codectypes.Any, 2) - sendAuthz := banktypes.NewSendAuthorization(sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(1000))), nil, addressCodec) - authorizations[0] = newAnyAuthorization(sendAuthz) - authorizations[1] = newAnyAuthorization(authz.NewGenericAuthorization(sdk.MsgTypeURL(&v1.MsgSubmitProposal{}))) - - return authorizations[r.Intn(len(authorizations))] +func generateRandomGrant(r *rand.Rand) *codectypes.Any { + examples := []*codectypes.Any{ + must(codectypes.NewAnyWithValue(banktypes.NewSendAuthorization(sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(1000))), nil, nil))), + must(codectypes.NewAnyWithValue(authz.NewGenericAuthorization(sdk.MsgTypeURL(&v1.MsgSubmitProposal{})))), + } + return examples[r.Intn(len(examples))] } -func newAnyAuthorization(a authz.Authorization) *codectypes.Any { - any, err := codectypes.NewAnyWithValue(a) +func must[T any](r T, err error) T { if err != nil { panic(err) } - - return any -} - -// RandomizedGenState generates a random GenesisState for authz. -func RandomizedGenState(simState *module.SimulationState) { - var grants []authz.GrantAuthorization - simState.AppParams.GetOrGenerate("authz", &grants, simState.Rand, func(r *rand.Rand) { - grants = genGrant(r, simState.Accounts, simState.GenTimestamp, simState.AddressCodec) - }) - - authzGrantsGenesis := authz.NewGenesisState(grants) - - simState.GenState[authz.ModuleName] = simState.Cdc.MustMarshalJSON(authzGrantsGenesis) + return r } diff --git a/x/authz/simulation/msg_factory.go b/x/authz/simulation/msg_factory.go new file mode 100644 index 000000000000..ab30a08ffee8 --- /dev/null +++ b/x/authz/simulation/msg_factory.go @@ -0,0 +1,103 @@ +package simulation + +import ( + "context" + "time" + + "cosmossdk.io/x/authz" + "cosmossdk.io/x/authz/keeper" + banktype "cosmossdk.io/x/bank/types" + + "github.com/cosmos/cosmos-sdk/simsx" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func MsgGrantFactory() simsx.SimMsgFactoryFn[*authz.MsgGrant] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *authz.MsgGrant) { + granter := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + grantee := testData.AnyAccount(reporter, simsx.ExcludeAccounts(granter)) + spendLimit := granter.LiquidBalance().RandSubsetCoins(reporter, simsx.WithSendEnabledCoins()) + + r := testData.Rand() + var expiration *time.Time + if t1 := r.Timestamp(); !t1.Before(simsx.BlockTime(ctx)) { + expiration = &t1 + } + // pick random authorization + authorizations := []authz.Authorization{ + banktype.NewSendAuthorization(spendLimit, nil, testData.AddressCodec()), + authz.NewGenericAuthorization(sdk.MsgTypeURL(&banktype.MsgSend{})), + } + randomAuthz := simsx.OneOf(r, authorizations) + + msg, err := authz.NewMsgGrant(granter.AddressBech32, grantee.AddressBech32, randomAuthz, expiration) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + return []simsx.SimAccount{granter}, msg + } +} + +func MsgExecFactory(k keeper.Keeper) simsx.SimMsgFactoryFn[*authz.MsgExec] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *authz.MsgExec) { + bankSendOnlyFilter := func(a authz.Authorization) bool { + _, ok := a.(*banktype.SendAuthorization) + return ok + } + granterAddr, granteeAddr, gAuthz := findGrant(ctx, k, reporter, bankSendOnlyFilter) + granter := testData.GetAccountbyAccAddr(reporter, granterAddr) + grantee := testData.GetAccountbyAccAddr(reporter, granteeAddr) + if reporter.IsSkipped() { + return nil, nil + } + amount := granter.LiquidBalance().RandSubsetCoins(reporter, simsx.WithSendEnabledCoins()) + amount = amount.Min(gAuthz.(*banktype.SendAuthorization).SpendLimit) + + payloadMsg := []sdk.Msg{banktype.NewMsgSend(granter.AddressBech32, grantee.AddressBech32, amount)} + msgExec := authz.NewMsgExec(grantee.AddressBech32, payloadMsg) + return []simsx.SimAccount{grantee}, &msgExec + } +} + +func MsgRevokeFactory(k keeper.Keeper) simsx.SimMsgFactoryFn[*authz.MsgRevoke] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *authz.MsgRevoke) { + granterAddr, granteeAddr, auth := findGrant(ctx, k, reporter) + granter := testData.GetAccountbyAccAddr(reporter, granterAddr) + grantee := testData.GetAccountbyAccAddr(reporter, granteeAddr) + if reporter.IsSkipped() { + return nil, nil + } + msgExec := authz.NewMsgRevoke(granter.AddressBech32, grantee.AddressBech32, auth.MsgTypeURL()) + return []simsx.SimAccount{granter}, &msgExec + } +} + +func findGrant( + ctx context.Context, + k keeper.Keeper, + reporter simsx.SimulationReporter, + acceptFilter ...func(a authz.Authorization) bool, +) (granterAddr, granteeAddr sdk.AccAddress, auth authz.Authorization) { + err := k.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, grant authz.Grant) (bool, error) { + a, err2 := grant.GetAuthorization() + if err2 != nil { + return true, err2 + } + for _, filter := range acceptFilter { + if !filter(a) { + return false, nil + } + } + granterAddr, granteeAddr, auth = granter, grantee, a + return true, nil + }) + if err != nil { + reporter.Skip(err.Error()) + return + } + if auth == nil { + reporter.Skip("no grant found") + } + return +} diff --git a/x/authz/simulation/operations.go b/x/authz/simulation/operations.go deleted file mode 100644 index 4c7c085d3b70..000000000000 --- a/x/authz/simulation/operations.go +++ /dev/null @@ -1,394 +0,0 @@ -package simulation - -import ( - "context" - "math/rand" - "time" - - gogoprotoany "github.com/cosmos/gogoproto/types/any" - - "cosmossdk.io/core/address" - "cosmossdk.io/core/appmodule" - corecontext "cosmossdk.io/core/context" - coregas "cosmossdk.io/core/gas" - coreheader "cosmossdk.io/core/header" - "cosmossdk.io/x/authz" - "cosmossdk.io/x/authz/keeper" - banktype "cosmossdk.io/x/bank/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - cdctypes "github.com/cosmos/cosmos-sdk/codec/types" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// authz message types -var ( - TypeMsgGrant = sdk.MsgTypeURL(&authz.MsgGrant{}) - TypeMsgRevoke = sdk.MsgTypeURL(&authz.MsgRevoke{}) - TypeMsgExec = sdk.MsgTypeURL(&authz.MsgExec{}) -) - -// Simulation operation weights constants -const ( - OpWeightMsgGrant = "op_weight_msg_grant" - OpWeightRevoke = "op_weight_msg_revoke" - OpWeightExec = "op_weight_msg_execute" -) - -// authz operations weights -const ( - WeightGrant = 100 - WeightRevoke = 90 - WeightExec = 90 -) - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - registry cdctypes.InterfaceRegistry, - appParams simtypes.AppParams, - cdc codec.JSONCodec, - txGen client.TxConfig, - ak authz.AccountKeeper, - bk authz.BankKeeper, - k keeper.Keeper, -) simulation.WeightedOperations { - var ( - weightMsgGrant int - weightExec int - weightRevoke int - ) - - appParams.GetOrGenerate(OpWeightMsgGrant, &weightMsgGrant, nil, func(_ *rand.Rand) { - weightMsgGrant = WeightGrant - }) - - appParams.GetOrGenerate(OpWeightExec, &weightExec, nil, func(_ *rand.Rand) { - weightExec = WeightExec - }) - - appParams.GetOrGenerate(OpWeightRevoke, &weightRevoke, nil, func(_ *rand.Rand) { - weightRevoke = WeightRevoke - }) - - pCdc := codec.NewProtoCodec(registry) - - return simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgGrant, - SimulateMsgGrant(pCdc, txGen, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightExec, - SimulateMsgExec(pCdc, txGen, ak, bk, k, registry), - ), - simulation.NewWeightedOperation( - weightRevoke, - SimulateMsgRevoke(pCdc, txGen, ak, bk, k), - ), - } -} - -// SimulateMsgGrant generates a MsgGrant with random values. -func SimulateMsgGrant( - cdc *codec.ProtoCodec, - txCfg client.TxConfig, - ak authz.AccountKeeper, - bk authz.BankKeeper, - _ keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - granter, _ := simtypes.RandomAcc(r, accs) - grantee, _ := simtypes.RandomAcc(r, accs) - - if granter.Address.Equals(grantee.Address) { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, "granter and grantee are same"), nil, nil - } - - granterAcc := ak.GetAccount(ctx, granter.Address) - spendableCoins := bk.SpendableCoins(ctx, granter.Address) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, err.Error()), nil, err - } - - spendLimit := spendableCoins.Sub(fees...) - if len(spendLimit) == 0 { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, "spend limit is nil"), nil, nil - } - - var expiration *time.Time - t1 := simtypes.RandTimestamp(r) - if !t1.Before(ctx.HeaderInfo().Time) { - expiration = &t1 - } - randomAuthz := generateRandomAuthorization(r, spendLimit, ak.AddressCodec()) - - granterAddr, err := ak.AddressCodec().BytesToString(granter.Address) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, "could not get granter address"), nil, nil - } - granteeAddr, err := ak.AddressCodec().BytesToString(grantee.Address) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, "could not get grantee address"), nil, nil - } - msg, err := authz.NewMsgGrant(granterAddr, granteeAddr, randomAuthz, expiration) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, err.Error()), nil, err - } - tx, err := simtestutil.GenSignedMockTx( - r, - txCfg, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{granterAcc.GetAccountNumber()}, - []uint64{granterAcc.GetSequence()}, - granter.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txCfg.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -func generateRandomAuthorization(r *rand.Rand, spendLimit sdk.Coins, addressCodec address.Codec) authz.Authorization { - authorizations := make([]authz.Authorization, 2) - sendAuthz := banktype.NewSendAuthorization(spendLimit, nil, addressCodec) - authorizations[0] = sendAuthz - authorizations[1] = authz.NewGenericAuthorization(sdk.MsgTypeURL(&banktype.MsgSend{})) - - return authorizations[r.Intn(len(authorizations))] -} - -// SimulateMsgRevoke generates a MsgRevoke with random values. -func SimulateMsgRevoke( - cdc *codec.ProtoCodec, - txCfg client.TxConfig, - ak authz.AccountKeeper, - bk authz.BankKeeper, - k keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - var granterAddr, granteeAddr sdk.AccAddress - var grant authz.Grant - hasGrant := false - - err := k.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, g authz.Grant) (bool, error) { - grant = g - granterAddr = granter - granteeAddr = grantee - hasGrant = true - return true, nil - }) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, err.Error()), nil, err - } - - if !hasGrant { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "no grants"), nil, nil - } - - granterAcc, ok := simtypes.FindAccount(accs, granterAddr) - if !ok { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "account not found"), nil, sdkerrors.ErrNotFound.Wrapf("account not found") - } - - spendableCoins := bk.SpendableCoins(ctx, granterAddr) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "fee error"), nil, err - } - - a, err := grant.GetAuthorization() - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "authorization error"), nil, err - } - - granterStrAddr, err := ak.AddressCodec().BytesToString(granterAddr) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "could not get granter address"), nil, nil - } - granteeStrAddr, err := ak.AddressCodec().BytesToString(granteeAddr) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "could not get grantee address"), nil, nil - } - msg := authz.NewMsgRevoke(granterStrAddr, granteeStrAddr, a.MsgTypeURL()) - account := ak.GetAccount(ctx, granterAddr) - tx, err := simtestutil.GenSignedMockTx( - r, - txCfg, - []sdk.Msg{&msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - granterAcc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, err.Error()), nil, err - } - - _, _, err = app.SimDeliver(txCfg.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "unable to execute tx: "+err.Error()), nil, err - } - - return simtypes.NewOperationMsg(&msg, true, ""), nil, nil - } -} - -// SimulateMsgExec generates a MsgExec with random values. -func SimulateMsgExec( - cdc *codec.ProtoCodec, - txCfg client.TxConfig, - ak authz.AccountKeeper, - bk authz.BankKeeper, - k keeper.Keeper, - unpacker gogoprotoany.AnyUnpacker, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - var granterAddr sdk.AccAddress - var granteeAddr sdk.AccAddress - var sendAuth *banktype.SendAuthorization - var err error - err = k.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, grant authz.Grant) (bool, error) { - granterAddr = granter - granteeAddr = grantee - var a authz.Authorization - a, err = grant.GetAuthorization() - if err != nil { - return true, err - } - var ok bool - sendAuth, ok = a.(*banktype.SendAuthorization) - return ok, nil - }) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, err - } - if sendAuth == nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "no grant found"), nil, nil - } - - grantee, ok := simtypes.FindAccount(accs, granteeAddr) - if !ok { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "Account not found"), nil, sdkerrors.ErrNotFound.Wrapf("grantee account not found") - } - - if _, ok := simtypes.FindAccount(accs, granterAddr); !ok { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "Account not found"), nil, sdkerrors.ErrNotFound.Wrapf("granter account not found") - } - - granterspendableCoins := bk.SpendableCoins(ctx, granterAddr) - coins := simtypes.RandSubsetCoins(r, granterspendableCoins) - // if coins slice is empty, we can not create valid banktype.MsgSend - if len(coins) == 0 { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "empty coins slice"), nil, nil - } - - // Check send_enabled status of each sent coin denom - if err := bk.IsSendEnabledCoins(ctx, coins...); err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, nil - } - - graStr, err := ak.AddressCodec().BytesToString(granterAddr) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, err - } - greStr, err := ak.AddressCodec().BytesToString(granteeAddr) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, err - } - - msg := []sdk.Msg{banktype.NewMsgSend(graStr, greStr, coins)} - - goCtx := context.WithValue(ctx.Context(), corecontext.EnvironmentContextKey, appmodule.Environment{ - HeaderService: headerService{}, - GasService: mockGasService{}, - }) - - _, err = sendAuth.Accept(goCtx, msg[0]) - if err != nil { - if sdkerrors.ErrInsufficientFunds.Is(err) { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, nil - } - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, err - - } - - msgExec := authz.NewMsgExec(greStr, msg) - granteeSpendableCoins := bk.SpendableCoins(ctx, granteeAddr) - fees, err := simtypes.RandomFees(r, granteeSpendableCoins) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "fee error"), nil, err - } - - granteeAcc := ak.GetAccount(ctx, granteeAddr) - tx, err := simtestutil.GenSignedMockTx( - r, - txCfg, - []sdk.Msg{&msgExec}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{granteeAcc.GetAccountNumber()}, - []uint64{granteeAcc.GetSequence()}, - grantee.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, err - } - - _, _, err = app.SimDeliver(txCfg.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, err - } - - err = msgExec.UnpackInterfaces(unpacker) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "unmarshal error"), nil, err - } - return simtypes.NewOperationMsg(&msgExec, true, "success"), nil, nil - } -} - -type headerService struct{} - -func (h headerService) HeaderInfo(ctx context.Context) coreheader.Info { - return sdk.UnwrapSDKContext(ctx).HeaderInfo() -} - -type mockGasService struct { - coregas.Service -} - -func (m mockGasService) GasMeter(ctx context.Context) coregas.Meter { - return mockGasMeter{} -} - -type mockGasMeter struct { - coregas.Meter -} - -func (m mockGasMeter) Consume(amount coregas.Gas, descriptor string) error { - return nil -} diff --git a/x/bank/client/cli/tx_test.go b/x/bank/client/cli/tx_test.go index 963fa918a29e..8f18458f79de 100644 --- a/x/bank/client/cli/tx_test.go +++ b/x/bank/client/cli/tx_test.go @@ -148,7 +148,6 @@ func (s *CLITestSuite) TestMultiSendTxCmd() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { ctx := svrcmd.CreateExecuteContext(context.Background()) diff --git a/x/bank/go.mod b/x/bank/go.mod index 8371adecaa2a..04c9a0af1d6a 100644 --- a/x/bank/go.mod +++ b/x/bank/go.mod @@ -5,7 +5,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 // indirect @@ -115,7 +115,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -164,7 +164,7 @@ require ( require cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 require ( - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect github.com/google/uuid v1.6.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect diff --git a/x/bank/go.sum b/x/bank/go.sum index cd6b45de5cf6..1f881f41bb27 100644 --- a/x/bank/go.sum +++ b/x/bank/go.sum @@ -4,8 +4,8 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +14,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -400,8 +400,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/bank/keeper/genesis_test.go b/x/bank/keeper/genesis_test.go index cd08a1178dcb..42f6221092cf 100644 --- a/x/bank/keeper/genesis_test.go +++ b/x/bank/keeper/genesis_test.go @@ -109,7 +109,6 @@ func (suite *KeeperTestSuite) TestTotalSupply() { } for _, tc := range testcases { - tc := tc suite.Run(tc.name, func() { if tc.expErrMsg != "" { suite.Require().ErrorContains(suite.bankKeeper.InitGenesis(suite.ctx, tc.genesis), tc.expErrMsg) diff --git a/x/bank/keeper/grpc_query_test.go b/x/bank/keeper/grpc_query_test.go index c563e4b60f66..6de9321d404c 100644 --- a/x/bank/keeper/grpc_query_test.go +++ b/x/bank/keeper/grpc_query_test.go @@ -83,8 +83,6 @@ func (suite *KeeperTestSuite) TestQueryBalance() { } for _, tc := range testCases { - tc := tc - suite.Run(tc.name, func() { res, err := queryClient.Balance(gocontext.Background(), tc.req) if tc.expectErrMsg == "" { diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index 120e8a2537f7..e625712f08b8 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -1377,30 +1377,26 @@ func (suite *KeeperTestSuite) TestMsgSendEvents() { suite.mockSendCoins(suite.ctx, acc0, accAddrs[1]) require.NoError(suite.bankKeeper.SendCoins(suite.ctx, accAddrs[0], accAddrs[1], newCoins)) event1 := coreevent.Event{ - Type: banktypes.EventTypeTransfer, - Attributes: []coreevent.Attribute{}, + Type: banktypes.EventTypeTransfer, + Attributes: func() ([]coreevent.Attribute, error) { + return []coreevent.Attribute{ + {Key: banktypes.AttributeKeyRecipient, Value: acc1StrAddr}, + {Key: banktypes.AttributeKeySender, Value: acc0StrAddr}, + {Key: sdk.AttributeKeyAmount, Value: newCoins.String()}, + }, nil + }, } - event1.Attributes = append( - event1.Attributes, - coreevent.Attribute{Key: banktypes.AttributeKeyRecipient, Value: acc1StrAddr}, - ) - event1.Attributes = append( - event1.Attributes, - coreevent.Attribute{Key: banktypes.AttributeKeySender, Value: acc0StrAddr}, - ) - event1.Attributes = append( - event1.Attributes, - coreevent.Attribute{Key: sdk.AttributeKeyAmount, Value: newCoins.String()}, - ) ctx := sdk.UnwrapSDKContext(suite.ctx) // events are shifted due to the funding account events events := ctx.EventManager().Events() require.Equal(8, len(events)) require.Equal(event1.Type, events[7].Type) - for i := range event1.Attributes { - require.Equal(event1.Attributes[i].Key, events[7].Attributes[i].Key) - require.Equal(event1.Attributes[i].Value, events[7].Attributes[i].Value) + attrs, err := event1.Attributes() + require.NoError(err) + for i := range attrs { + require.Equal(attrs[i].Key, events[7].Attributes[i].Key) + require.Equal(attrs[i].Value, events[7].Attributes[i].Value) } } @@ -1462,36 +1458,41 @@ func (suite *KeeperTestSuite) TestMsgMultiSendEvents() { require.Equal(25, len(events)) // 25 due to account funding + coin_spent + coin_recv events event1 := coreevent.Event{ - Type: banktypes.EventTypeTransfer, - Attributes: []coreevent.Attribute{}, + Type: banktypes.EventTypeTransfer, + Attributes: func() ([]coreevent.Attribute, error) { + return []coreevent.Attribute{ + {Key: banktypes.AttributeKeyRecipient, Value: acc2StrAddr}, + {Key: sdk.AttributeKeySender, Value: acc0StrAddr}, + {Key: sdk.AttributeKeyAmount, Value: newCoins.String()}, + }, nil + }, } - event1.Attributes = append( - event1.Attributes, - coreevent.Attribute{Key: banktypes.AttributeKeyRecipient, Value: acc2StrAddr}, - coreevent.Attribute{Key: sdk.AttributeKeySender, Value: acc0StrAddr}, - coreevent.Attribute{Key: sdk.AttributeKeyAmount, Value: newCoins.String()}, - ) event2 := coreevent.Event{ - Type: banktypes.EventTypeTransfer, - Attributes: []coreevent.Attribute{}, + Type: banktypes.EventTypeTransfer, + Attributes: func() ([]coreevent.Attribute, error) { + attrs := []coreevent.Attribute{ + {Key: banktypes.AttributeKeyRecipient, Value: acc3StrAddr}, + {Key: sdk.AttributeKeySender, Value: acc0StrAddr}, + {Key: sdk.AttributeKeyAmount, Value: newCoins2.String()}, + } + return attrs, nil + }, } - event2.Attributes = append( - event2.Attributes, - coreevent.Attribute{Key: banktypes.AttributeKeyRecipient, Value: acc3StrAddr}, - coreevent.Attribute{Key: sdk.AttributeKeySender, Value: acc0StrAddr}, - coreevent.Attribute{Key: sdk.AttributeKeyAmount, Value: newCoins2.String()}, - ) // events are shifted due to the funding account events require.Equal(event1.Type, events[22].Type) - for i := range event1.Attributes { - require.Equal(event1.Attributes[i].Key, events[22].Attributes[i].Key) - require.Equal(event1.Attributes[i].Value, events[22].Attributes[i].Value) + attrs1, err := event1.Attributes() + require.NoError(err) + for i := range attrs1 { + require.Equal(attrs1[i].Key, events[22].Attributes[i].Key) + require.Equal(attrs1[i].Value, events[22].Attributes[i].Value) } require.Equal(event2.Type, events[24].Type) - for i := range event2.Attributes { - require.Equal(event2.Attributes[i].Key, events[24].Attributes[i].Key) - require.Equal(event2.Attributes[i].Value, events[24].Attributes[i].Value) + attrs2, err := event2.Attributes() + require.NoError(err) + for i := range attrs2 { + require.Equal(attrs2[i].Key, events[24].Attributes[i].Key) + require.Equal(attrs2[i].Value, events[24].Attributes[i].Value) } } diff --git a/x/bank/keeper/msg_server_test.go b/x/bank/keeper/msg_server_test.go index ecc09f79ba78..c02f6943b90a 100644 --- a/x/bank/keeper/msg_server_test.go +++ b/x/bank/keeper/msg_server_test.go @@ -52,7 +52,6 @@ func (suite *KeeperTestSuite) TestMsgUpdateParams() { } for _, tc := range testCases { - tc := tc suite.Run(tc.name, func() { _, err := suite.msgServer.UpdateParams(suite.ctx, tc.input) @@ -145,7 +144,6 @@ func (suite *KeeperTestSuite) TestMsgSend() { } for _, tc := range testCases { - tc := tc suite.Run(tc.name, func() { suite.mockMintCoins(minterAcc) err := suite.bankKeeper.MintCoins(suite.ctx, minterAcc.Name, origCoins) @@ -252,7 +250,6 @@ func (suite *KeeperTestSuite) TestMsgMultiSend() { } for _, tc := range testCases { - tc := tc suite.Run(tc.name, func() { suite.mockMintCoins(minterAcc) err := suite.bankKeeper.MintCoins(suite.ctx, minterAcc.Name, origCoins) @@ -422,7 +419,6 @@ func (suite *KeeperTestSuite) TestMsgBurn() { } for _, tc := range testCases { - tc := tc suite.Run(tc.name, func() { suite.mockMintCoins(multiPermAcc) err := suite.bankKeeper.MintCoins(suite.ctx, multiPermAcc.Name, sdk.Coins{}.Add(origCoins)) diff --git a/x/bank/module.go b/x/bank/module.go index 721c3dc6a0cf..49aa2981b918 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -18,6 +18,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simsx" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" @@ -160,19 +161,17 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { simulation.RandomizedGenState(simState) } -// ProposalMsgs returns msgs used for governance proposals for simulations. -func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { - return simulation.ProposalMsgs() -} - // RegisterStoreDecoder registers a decoder for supply module's types func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[types.StoreKey] = simtypes.NewStoreDecoderFuncFromCollectionsSchema(am.keeper.(keeper.BaseKeeper).Schema) } -// WeightedOperations returns the all the gov module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - simState.AppParams, simState.Cdc, simState.TxConfig, am.accountKeeper, am.keeper, - ) +// ProposalMsgsX returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_update_params", 100), simulation.MsgUpdateParamsFactory()) +} + +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_send", 100), simulation.MsgSendFactory()) + reg.Add(weights.Get("msg_multisend", 10), simulation.MsgMultiSendFactory()) } diff --git a/x/bank/simulation/genesis.go b/x/bank/simulation/genesis.go index 9e8b8512b827..f2f9b2e2f907 100644 --- a/x/bank/simulation/genesis.go +++ b/x/bank/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" sdkmath "cosmossdk.io/math" @@ -99,10 +97,5 @@ func RandomizedGenState(simState *module.SimulationState) { SendEnabled: sendEnabled, } - paramsBytes, err := json.MarshalIndent(&bankGenesis.Params, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated bank parameters:\n%s\n", paramsBytes) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(&bankGenesis) } diff --git a/x/bank/simulation/genesis_test.go b/x/bank/simulation/genesis_test.go index f5e93943d739..8fea56ada6db 100644 --- a/x/bank/simulation/genesis_test.go +++ b/x/bank/simulation/genesis_test.go @@ -83,8 +83,6 @@ func TestRandomizedGenState1(t *testing.T) { } for _, tt := range tests { - tt := tt - require.Panicsf(t, func() { simulation.RandomizedGenState(&tt.simState) }, tt.panicMsg) } } diff --git a/x/bank/simulation/msg_factory.go b/x/bank/simulation/msg_factory.go new file mode 100644 index 000000000000..ac9a9ff388a2 --- /dev/null +++ b/x/bank/simulation/msg_factory.go @@ -0,0 +1,87 @@ +package simulation + +import ( + "context" + "slices" + + "cosmossdk.io/x/bank/types" + + "github.com/cosmos/cosmos-sdk/simsx" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func MsgSendFactory() simsx.SimMsgFactoryFn[*types.MsgSend] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgSend) { + from := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + to := testData.AnyAccount(reporter, simsx.ExcludeAccounts(from)) + coins := from.LiquidBalance().RandSubsetCoins(reporter, simsx.WithSendEnabledCoins()) + return []simsx.SimAccount{from}, types.NewMsgSend(from.AddressBech32, to.AddressBech32, coins) + } +} + +func MsgMultiSendFactory() simsx.SimMsgFactoryFn[*types.MsgMultiSend] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgMultiSend) { + r := testData.Rand() + var ( + sending = make([]types.Input, 1) + receiving = make([]types.Output, r.Intn(3)+1) + senderAcc = make([]simsx.SimAccount, len(sending)) + totalSentCoins sdk.Coins + uniqueAccountsFilter = simsx.UniqueAccounts() + ) + for i := range sending { + // generate random input fields, ignore to address + from := testData.AnyAccount(reporter, simsx.WithSpendableBalance(), uniqueAccountsFilter) + if reporter.IsSkipped() { + return nil, nil + } + coins := from.LiquidBalance().RandSubsetCoins(reporter, simsx.WithSendEnabledCoins()) + + // set signer privkey + senderAcc[i] = from + + // set next input and accumulate total sent coins + sending[i] = types.NewInput(from.AddressBech32, coins) + totalSentCoins = totalSentCoins.Add(coins...) + } + + for i := range receiving { + receiver := testData.AnyAccount(reporter) + if reporter.IsSkipped() { + return nil, nil + } + + var outCoins sdk.Coins + // split total sent coins into random subsets for output + if i == len(receiving)-1 { + // last one receives remaining amount + outCoins = totalSentCoins + } else { + // take random subset of remaining coins for output + // and update remaining coins + outCoins = r.SubsetCoins(totalSentCoins) + totalSentCoins = totalSentCoins.Sub(outCoins...) + } + + receiving[i] = types.NewOutput(receiver.AddressBech32, outCoins) + } + + // remove any entries that have no coins + receiving = slices.DeleteFunc(receiving, func(o types.Output) bool { + return o.Address == "" || o.Coins.Empty() + }) + return senderAcc, &types.MsgMultiSend{Inputs: sending, Outputs: receiving} + } +} + +// MsgUpdateParamsFactory creates a gov proposal for param updates +func MsgUpdateParamsFactory() simsx.SimMsgFactoryFn[*types.MsgUpdateParams] { + return func(_ context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgUpdateParams) { + params := types.DefaultParams() + params.DefaultSendEnabled = testData.Rand().Intn(2) == 0 + return nil, &types.MsgUpdateParams{ + Authority: testData.ModuleAccountAddress(reporter, "gov"), + Params: params, + } + } +} diff --git a/x/bank/simulation/operations.go b/x/bank/simulation/operations.go deleted file mode 100644 index d662687cfe07..000000000000 --- a/x/bank/simulation/operations.go +++ /dev/null @@ -1,472 +0,0 @@ -package simulation - -import ( - "math/rand" - - "cosmossdk.io/x/bank/keeper" - "cosmossdk.io/x/bank/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - OpWeightMsgSend = "op_weight_msg_send" - OpWeightMsgMultiSend = "op_weight_msg_multisend" - DefaultWeightMsgSend = 100 // from simappparams.DefaultWeightMsgSend - DefaultWeightMsgMultiSend = 10 // from simappparams.DefaultWeightMsgMultiSend - - distributionModuleName = "distribution" -) - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - appParams simtypes.AppParams, - cdc codec.JSONCodec, - txGen client.TxConfig, - ak types.AccountKeeper, - bk keeper.Keeper, -) simulation.WeightedOperations { - var weightMsgSend, weightMsgMultiSend int - appParams.GetOrGenerate(OpWeightMsgSend, &weightMsgSend, nil, func(_ *rand.Rand) { - weightMsgSend = DefaultWeightMsgSend - }) - - appParams.GetOrGenerate(OpWeightMsgMultiSend, &weightMsgMultiSend, nil, func(_ *rand.Rand) { - weightMsgMultiSend = DefaultWeightMsgMultiSend - }) - - return simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgSend, - SimulateMsgSend(txGen, ak, bk), - ), - simulation.NewWeightedOperation( - weightMsgMultiSend, - SimulateMsgMultiSend(txGen, ak, bk), - ), - } -} - -// SimulateMsgSend tests and runs a single msg send where both -// accounts already exist. -func SimulateMsgSend( - txGen client.TxConfig, - ak types.AccountKeeper, - bk keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgSend{}) - from, to, coins, skip := randomSendFields(r, ctx, accs, bk, ak) - - // if coins slice is empty, we can not create valid types.MsgSend - if len(coins) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "empty coins slice"), nil, nil - } - - // Check send_enabled status of each coin denom - if err := bk.IsSendEnabledCoins(ctx, coins...); err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil - } - if skip { - return simtypes.NoOpMsg(types.ModuleName, msgType, "skip all transfers"), nil, nil - } - - fromstr, err := ak.AddressCodec().BytesToString(from.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil - } - tostr, err := ak.AddressCodec().BytesToString(to.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil - } - - msg := types.NewMsgSend(fromstr, tostr, coins) - - if err := sendMsgSend(r, app, txGen, bk, ak, msg, ctx, chainID, []cryptotypes.PrivKey{from.PrivKey}); err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "invalid transfers"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, nil - } -} - -// SimulateMsgSendToModuleAccount tests and runs a single msg send where both -// accounts already exist. -func SimulateMsgSendToModuleAccount( - txGen client.TxConfig, - ak types.AccountKeeper, - bk keeper.Keeper, - moduleAccount int, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgSend{}) - from := accs[0] - to := getModuleAccounts(ak, ctx, moduleAccount)[0] - - spendable := bk.SpendableCoins(ctx, from.Address) - coins := simtypes.RandSubsetCoins(r, spendable) - // if coins slice is empty, we can not create valid types.MsgSend - if len(coins) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "empty coins slice"), nil, nil - } - // Check send_enabled status of each coin denom - if err := bk.IsSendEnabledCoins(ctx, coins...); err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil - } - fromstr, err := ak.AddressCodec().BytesToString(from.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil - } - tostr, err := ak.AddressCodec().BytesToString(to.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil - } - msg := types.NewMsgSend(fromstr, tostr, coins) - - if err := sendMsgSend(r, app, txGen, bk, ak, msg, ctx, chainID, []cryptotypes.PrivKey{from.PrivKey}); err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "invalid transfers"), nil, err - } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil - } -} - -// sendMsgSend sends a transaction with a MsgSend from a provided random account. -func sendMsgSend( - r *rand.Rand, app simtypes.AppEntrypoint, - txGen client.TxConfig, - bk keeper.Keeper, ak types.AccountKeeper, - msg *types.MsgSend, ctx sdk.Context, chainID string, privkeys []cryptotypes.PrivKey, -) error { - var ( - fees sdk.Coins - err error - ) - - from, err := ak.AddressCodec().StringToBytes(msg.FromAddress) - if err != nil { - return err - } - - account := ak.GetAccount(ctx, from) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - coins, hasNeg := spendable.SafeSub(msg.Amount...) - if !hasNeg { - fees, err = simtypes.RandomFees(r, coins) - if err != nil { - return err - } - } - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - privkeys..., - ) - if err != nil { - return err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return err - } - - return nil -} - -// SimulateMsgMultiSend tests and runs a single msg multisend, with randomized, capped number of inputs/outputs. -// all accounts in msg fields exist in state -func SimulateMsgMultiSend(txGen client.TxConfig, ak types.AccountKeeper, bk keeper.Keeper) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgMultiSend{}) - - // random number of inputs/outputs between [1, 3] - inputs := make([]types.Input, r.Intn(1)+1) //nolint:staticcheck // SA4030: (*math/rand.Rand).Intn(n) generates a random value 0 <= x < n; that is, the generated values don't include n; r.Intn(1) therefore always returns 0 - outputs := make([]types.Output, r.Intn(3)+1) - - // collect signer privKeys - privs := make([]cryptotypes.PrivKey, len(inputs)) - - // use map to check if address already exists as input - usedAddrs := make(map[string]bool) - - var totalSentCoins sdk.Coins - for i := range inputs { - // generate random input fields, ignore to address - from, _, coins, skip := randomSendFields(r, ctx, accs, bk, ak) - - fromAddr, err := ak.AddressCodec().BytesToString(from.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "could not retrieve address"), nil, err - } - - // make sure account is fresh and not used in previous input - for usedAddrs[fromAddr] { - from, _, coins, skip = randomSendFields(r, ctx, accs, bk, ak) - } - - if skip { - return simtypes.NoOpMsg(types.ModuleName, msgType, "skip all transfers"), nil, nil - } - - // set input address in used address map - usedAddrs[fromAddr] = true - - // set signer privkey - privs[i] = from.PrivKey - - // set next input and accumulate total sent coins - inputs[i] = types.NewInput(fromAddr, coins) - totalSentCoins = totalSentCoins.Add(coins...) - } - - // Check send_enabled status of each sent coin denom - if err := bk.IsSendEnabledCoins(ctx, totalSentCoins...); err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil - } - - for o := range outputs { - out, _ := simtypes.RandomAcc(r, accs) - outAddr, err := ak.AddressCodec().BytesToString(out.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "could not retrieve output address"), nil, err - } - - var outCoins sdk.Coins - // split total sent coins into random subsets for output - if o == len(outputs)-1 { - outCoins = totalSentCoins - } else { - // take random subset of remaining coins for output - // and update remaining coins - outCoins = simtypes.RandSubsetCoins(r, totalSentCoins) - totalSentCoins = totalSentCoins.Sub(outCoins...) - } - - outputs[o] = types.NewOutput(outAddr, outCoins) - } - - // remove any output that has no coins - - for i := 0; i < len(outputs); { - if outputs[i].Coins.Empty() { - outputs[i] = outputs[len(outputs)-1] - outputs = outputs[:len(outputs)-1] - } else { - // continue onto next coin - i++ - } - } - - msg := &types.MsgMultiSend{ - Inputs: inputs, - Outputs: outputs, - } - err := sendMsgMultiSend(r, app, txGen, bk, ak, msg, ctx, chainID, privs) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "invalid transfers"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, nil - } -} - -// SimulateMsgMultiSendToModuleAccount sends coins to Module Accounts -func SimulateMsgMultiSendToModuleAccount( - txGen client.TxConfig, - ak types.AccountKeeper, - bk keeper.Keeper, - moduleAccount int, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgMultiSend{}) - inputs := make([]types.Input, 2) - outputs := make([]types.Output, moduleAccount) - // collect signer privKeys - privs := make([]cryptotypes.PrivKey, len(inputs)) - var totalSentCoins sdk.Coins - for i := range inputs { - sender := accs[i] - privs[i] = sender.PrivKey - senderAddr, err := ak.AddressCodec().BytesToString(sender.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, err - } - spendable := bk.SpendableCoins(ctx, sender.Address) - coins := simtypes.RandSubsetCoins(r, spendable) - inputs[i] = types.NewInput(senderAddr, coins) - totalSentCoins = totalSentCoins.Add(coins...) - } - if err := bk.IsSendEnabledCoins(ctx, totalSentCoins...); err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil - } - moduleAccounts := getModuleAccounts(ak, ctx, moduleAccount) - for i := range outputs { - outAddr, err := ak.AddressCodec().BytesToString(moduleAccounts[i].Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "could not retrieve output address"), nil, err - } - - var outCoins sdk.Coins - // split total sent coins into random subsets for output - if i == len(outputs)-1 { - outCoins = totalSentCoins - } else { - // take random subset of remaining coins for output - // and update remaining coins - outCoins = simtypes.RandSubsetCoins(r, totalSentCoins) - totalSentCoins = totalSentCoins.Sub(outCoins...) - } - outputs[i] = types.NewOutput(outAddr, outCoins) - } - // remove any output that has no coins - for i := 0; i < len(outputs); { - if outputs[i].Coins.Empty() { - outputs[i] = outputs[len(outputs)-1] - outputs = outputs[:len(outputs)-1] - } else { - // continue onto next coin - i++ - } - } - msg := &types.MsgMultiSend{ - Inputs: inputs, - Outputs: outputs, - } - err := sendMsgMultiSend(r, app, txGen, bk, ak, msg, ctx, chainID, privs) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "invalid transfers"), nil, err - } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil - } -} - -// sendMsgMultiSend sends a transaction with a MsgMultiSend from a provided random -// account. -func sendMsgMultiSend( - r *rand.Rand, app simtypes.AppEntrypoint, - txGen client.TxConfig, - bk keeper.Keeper, ak types.AccountKeeper, - msg *types.MsgMultiSend, ctx sdk.Context, chainID string, privkeys []cryptotypes.PrivKey, -) error { - accountNumbers := make([]uint64, len(msg.Inputs)) - sequenceNumbers := make([]uint64, len(msg.Inputs)) - for i := 0; i < len(msg.Inputs); i++ { - addr, err := ak.AddressCodec().StringToBytes(msg.Inputs[i].Address) - if err != nil { - panic(err) - } - - acc := ak.GetAccount(ctx, addr) - accountNumbers[i] = acc.GetAccountNumber() - sequenceNumbers[i] = acc.GetSequence() - } - var ( - fees sdk.Coins - err error - ) - - addr, err := ak.AddressCodec().StringToBytes(msg.Inputs[0].Address) - if err != nil { - panic(err) - } - // feePayer is the first signer, i.e. first input address - feePayer := ak.GetAccount(ctx, addr) - spendable := bk.SpendableCoins(ctx, feePayer.GetAddress()) - coins, hasNeg := spendable.SafeSub(msg.Inputs[0].Coins...) - if !hasNeg { - fees, err = simtypes.RandomFees(r, coins) - if err != nil { - return err - } - } - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - accountNumbers, - sequenceNumbers, - privkeys..., - ) - if err != nil { - return err - } - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return err - } - return nil -} - -// randomSendFields returns the sender and recipient simulation accounts as well -// as the transferred amount. -func randomSendFields( - r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, bk keeper.Keeper, ak types.AccountKeeper, -) (simtypes.Account, simtypes.Account, sdk.Coins, bool) { - from, _ := simtypes.RandomAcc(r, accs) - to, _ := simtypes.RandomAcc(r, accs) - - // disallow sending money to yourself - for from.PubKey.Equals(to.PubKey) { - to, _ = simtypes.RandomAcc(r, accs) - } - - acc := ak.GetAccount(ctx, from.Address) - if acc == nil { - return from, to, nil, true - } - - spendable := bk.SpendableCoins(ctx, acc.GetAddress()) - - sendCoins := simtypes.RandSubsetCoins(r, spendable) - if sendCoins.Empty() { - return from, to, nil, true - } - - return from, to, sendCoins, false -} - -func getModuleAccounts(ak types.AccountKeeper, ctx sdk.Context, moduleAccount int) []simtypes.Account { - moduleAccounts := make([]simtypes.Account, moduleAccount) - - for i := 0; i < moduleAccount; i++ { - acc := ak.GetModuleAccount(ctx, distributionModuleName) - mAcc := simtypes.Account{ - Address: acc.GetAddress(), - PrivKey: nil, - ConsKey: nil, - PubKey: acc.GetPubKey(), - } - moduleAccounts[i] = mAcc - } - - return moduleAccounts -} diff --git a/x/bank/types/balance_test.go b/x/bank/types/balance_test.go index c208f88c218c..85ed43d035c2 100644 --- a/x/bank/types/balance_test.go +++ b/x/bank/types/balance_test.go @@ -105,7 +105,6 @@ func TestBalanceValidate(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := tc.balance.Validate() @@ -129,7 +128,6 @@ func TestBalance_GetAddress(t *testing.T) { {"valid address", "cosmos1vy0ga0klndqy92ceqehfkvgmn4t94eteq4hmqv", false}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { b := bank.Balance{Address: tt.Address} if !tt.err { diff --git a/x/bank/types/genesis_test.go b/x/bank/types/genesis_test.go index 93805ac84b57..f7412df117fa 100644 --- a/x/bank/types/genesis_test.go +++ b/x/bank/types/genesis_test.go @@ -146,7 +146,6 @@ func TestGenesisStateValidate(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(tt *testing.T) { err := tc.genesisState.Validate() diff --git a/x/bank/types/metadata_test.go b/x/bank/types/metadata_test.go index 3d8ba100005a..648e13195147 100644 --- a/x/bank/types/metadata_test.go +++ b/x/bank/types/metadata_test.go @@ -217,7 +217,6 @@ func TestMetadataValidate(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := tc.metadata.Validate() @@ -259,7 +258,6 @@ func TestMarshalJSONMetaData(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { bz, err := cdc.MarshalJSON(tc.input) require.NoError(t, err) diff --git a/x/circuit/autocli.go b/x/circuit/autocli.go index e9055caf5185..898028247808 100644 --- a/x/circuit/autocli.go +++ b/x/circuit/autocli.go @@ -43,7 +43,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { "SOME_MSGS" = 1, "ALL_MSGS" = 2, "SUPER_ADMIN" = 3,`, - Example: fmt.Sprintf(`%s circuit authorize [address] '{"level":1,"limit_type_urls":["cosmos.bank.v1beta1.MsgSend,cosmos.bank.v1beta1.MsgMultiSend"]}'"`, version.AppName), + Example: fmt.Sprintf(`%s circuit authorize [address] '{"level":1,"limit_type_urls":["/cosmos.bank.v1beta1.MsgSend, /cosmos.bank.v1beta1.MsgMultiSend"]}'"`, version.AppName), PositionalArgs: []*autocliv1.PositionalArgDescriptor{ {ProtoField: "grantee"}, {ProtoField: "permissions"}, // TODO(@julienrbrt) Support flattening msg for setting each field as a positional arg @@ -53,7 +53,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { RpcMethod: "TripCircuitBreaker", Use: "disable ", Short: "Disable a message from being executed", - Example: fmt.Sprintf(`%s circuit disable "cosmos.bank.v1beta1.MsgSend cosmos.bank.v1beta1.MsgMultiSend"`, version.AppName), + Example: fmt.Sprintf(`%s circuit disable "/cosmos.bank.v1beta1.MsgSend /cosmos.bank.v1beta1.MsgMultiSend"`, version.AppName), PositionalArgs: []*autocliv1.PositionalArgDescriptor{ {ProtoField: "msg_type_urls", Varargs: true}, }, @@ -62,7 +62,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { RpcMethod: "ResetCircuitBreaker", Use: "reset ", Short: "Enable a message to be executed", - Example: fmt.Sprintf(`%s circuit reset "cosmos.bank.v1beta1.MsgSend cosmos.bank.v1beta1.MsgMultiSend"`, version.AppName), + Example: fmt.Sprintf(`%s circuit reset "/cosmos.bank.v1beta1.MsgSend /cosmos.bank.v1beta1.MsgMultiSend"`, version.AppName), PositionalArgs: []*autocliv1.PositionalArgDescriptor{ {ProtoField: "msg_type_urls", Varargs: true}, }, diff --git a/x/circuit/go.mod b/x/circuit/go.mod index c35b3e0e5469..9744ee165e0c 100644 --- a/x/circuit/go.mod +++ b/x/circuit/go.mod @@ -5,7 +5,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 @@ -24,7 +24,7 @@ require ( buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/log v1.4.1 // indirect cosmossdk.io/math v1.3.0 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -119,7 +119,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/x/circuit/go.sum b/x/circuit/go.sum index a658644fd79f..5b3cf3f73e5b 100644 --- a/x/circuit/go.sum +++ b/x/circuit/go.sum @@ -6,8 +6,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -402,8 +402,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/consensus/go.mod b/x/consensus/go.mod index 108f006087a0..8c71ccf1807c 100644 --- a/x/consensus/go.mod +++ b/x/consensus/go.mod @@ -5,7 +5,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/depinject v1.0.0 cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc @@ -27,7 +27,7 @@ require ( cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/log v1.4.1 // indirect cosmossdk.io/math v1.3.0 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -118,7 +118,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/x/consensus/go.sum b/x/consensus/go.sum index 27af6ac5b1b3..4b8596484eb6 100644 --- a/x/consensus/go.sum +++ b/x/consensus/go.sum @@ -6,8 +6,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -402,8 +402,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/distribution/client/common/common_test.go b/x/distribution/client/common/common_test.go index 2020e3b8f109..020047024ead 100644 --- a/x/distribution/client/common/common_test.go +++ b/x/distribution/client/common/common_test.go @@ -35,7 +35,6 @@ func TestQueryDelegationRewardsAddrValidation(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { _, _, err := QueryDelegationRewards(clientCtx, tt.args.delAddr, tt.args.valAddr) require.True(t, err != nil, tt.wantErr) diff --git a/x/distribution/depinject.go b/x/distribution/depinject.go index 1701e88b8bf2..4803b4d34c60 100644 --- a/x/distribution/depinject.go +++ b/x/distribution/depinject.go @@ -74,7 +74,7 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { authorityAddr, ) - m := NewAppModule(in.Cdc, k, in.AccountKeeper, in.BankKeeper, in.StakingKeeper) + m := NewAppModule(in.Cdc, k, in.StakingKeeper) return ModuleOutputs{ DistrKeeper: k, diff --git a/x/distribution/go.mod b/x/distribution/go.mod index 1d0ab2329dc9..fe3ada3ff7c6 100644 --- a/x/distribution/go.mod +++ b/x/distribution/go.mod @@ -5,7 +5,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 @@ -24,14 +24,13 @@ require ( github.com/stretchr/testify v1.9.0 google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 google.golang.org/grpc v1.66.2 - gotest.tools/v3 v3.5.1 ) require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/log v1.4.1 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/tx v0.13.3 // indirect filippo.io/edwards25519 v1.1.0 // indirect @@ -121,7 +120,7 @@ require ( github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -163,6 +162,7 @@ require ( google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + gotest.tools/v3 v3.5.1 // indirect pgregory.net/rapid v1.1.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/x/distribution/go.sum b/x/distribution/go.sum index cd6b45de5cf6..1f881f41bb27 100644 --- a/x/distribution/go.sum +++ b/x/distribution/go.sum @@ -4,8 +4,8 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +14,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -400,8 +400,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/distribution/keeper/grpc_query_test.go b/x/distribution/keeper/grpc_query_test.go index 84fa95def6cc..24271354930f 100644 --- a/x/distribution/keeper/grpc_query_test.go +++ b/x/distribution/keeper/grpc_query_test.go @@ -38,7 +38,6 @@ func TestQueryParams(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { out, err := queryServer.Params(ctx, tc.req) if tc.errMsg == "" { @@ -94,7 +93,6 @@ func TestQueryValidatorDistributionInfo(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { out, err := queryServer.ValidatorDistributionInfo(ctx, tc.req) if tc.errMsg == "" { @@ -173,7 +171,6 @@ func TestQueryCommunityPool(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { out, err := queryServer.CommunityPool(ctx, tc.req) if tc.errMsg == "" { diff --git a/x/distribution/keeper/msg_server_test.go b/x/distribution/keeper/msg_server_test.go index 03f4e8c88565..a7acde70e34b 100644 --- a/x/distribution/keeper/msg_server_test.go +++ b/x/distribution/keeper/msg_server_test.go @@ -56,7 +56,6 @@ func TestMsgSetWithdrawAddress(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { _, err := msgServer.SetWithdrawAddress(ctx, tc.msg) if tc.errMsg == "" { @@ -112,7 +111,6 @@ func TestMsgWithdrawDelegatorReward(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { if tc.preRun != nil { tc.preRun() @@ -158,7 +156,6 @@ func TestMsgWithdrawValidatorCommission(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { if tc.preRun != nil { tc.preRun() @@ -206,7 +203,6 @@ func TestMsgFundCommunityPool(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { _, err := msgServer.FundCommunityPool(ctx, tc.msg) //nolint:staticcheck // Testing deprecated method if tc.errMsg == "" { @@ -267,7 +263,6 @@ func TestMsgUpdateParams(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { _, err := msgServer.UpdateParams(ctx, tc.msg) if tc.errMsg == "" { @@ -340,7 +335,6 @@ func TestMsgCommunityPoolSpend(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { _, err := msgServer.CommunityPoolSpend(ctx, tc.msg) //nolint:staticcheck // Testing deprecated method if tc.errMsg == "" { @@ -373,7 +367,6 @@ func TestMsgDepositValidatorRewardsPool(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { _, err := msgServer.DepositValidatorRewardsPool(ctx, tc.msg) if tc.errMsg == "" { diff --git a/x/distribution/module.go b/x/distribution/module.go index db043b3bdabe..eb7de978c6d1 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -18,6 +18,7 @@ import ( sdkclient "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simsx" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" @@ -43,21 +44,14 @@ var ( type AppModule struct { cdc codec.Codec keeper keeper.Keeper - accountKeeper types.AccountKeeper - bankKeeper types.BankKeeper stakingKeeper types.StakingKeeper } // NewAppModule creates a new AppModule object -func NewAppModule( - cdc codec.Codec, keeper keeper.Keeper, accountKeeper types.AccountKeeper, - bankKeeper types.BankKeeper, stakingKeeper types.StakingKeeper, -) AppModule { +func NewAppModule(cdc codec.Codec, keeper keeper.Keeper, stakingKeeper types.StakingKeeper) AppModule { return AppModule{ cdc: cdc, keeper: keeper, - accountKeeper: accountKeeper, - bankKeeper: bankKeeper, stakingKeeper: stakingKeeper, } } @@ -173,20 +167,18 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { simulation.RandomizedGenState(simState) } -// ProposalMsgs returns msgs used for governance proposals for simulations. -func (AppModule) ProposalMsgs(_ module.SimulationState) []simtypes.WeightedProposalMsg { - return simulation.ProposalMsgs() -} - // RegisterStoreDecoder registers a decoder for distribution module's types func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) } -// WeightedOperations returns the all the gov module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - simState.AppParams, simState.Cdc, simState.TxConfig, - am.accountKeeper, am.bankKeeper, am.keeper, am.stakingKeeper, - ) +// ProposalMsgsX returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_update_params", 100), simulation.MsgUpdateParamsFactory()) +} + +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_set_withdraw_address", 50), simulation.MsgSetWithdrawAddressFactory(am.keeper)) + reg.Add(weights.Get("msg_withdraw_delegation_reward", 50), simulation.MsgWithdrawDelegatorRewardFactory(am.keeper, am.stakingKeeper)) + reg.Add(weights.Get("msg_withdraw_validator_commission", 50), simulation.MsgWithdrawValidatorCommissionFactory(am.keeper, am.stakingKeeper)) } diff --git a/x/distribution/simulation/decoder_test.go b/x/distribution/simulation/decoder_test.go index c96f8444840f..52b4d1b4886f 100644 --- a/x/distribution/simulation/decoder_test.go +++ b/x/distribution/simulation/decoder_test.go @@ -51,7 +51,6 @@ func TestDecodeDistributionStore(t *testing.T) { {"other", ""}, } for i, tt := range tests { - i, tt := i, tt t.Run(tt.name, func(t *testing.T) { switch i { case len(tests) - 1: diff --git a/x/distribution/simulation/genesis.go b/x/distribution/simulation/genesis.go index bccf952ad99d..4b0c42c9b467 100644 --- a/x/distribution/simulation/genesis.go +++ b/x/distribution/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" "cosmossdk.io/math" @@ -43,10 +41,5 @@ func RandomizedGenState(simState *module.SimulationState) { }, } - bz, err := json.MarshalIndent(&distrGenesis, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated distribution parameters:\n%s\n", bz) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(&distrGenesis) } diff --git a/x/distribution/simulation/genesis_test.go b/x/distribution/simulation/genesis_test.go index 6c74a5e2bffc..46ff6aedb755 100644 --- a/x/distribution/simulation/genesis_test.go +++ b/x/distribution/simulation/genesis_test.go @@ -77,8 +77,6 @@ func TestRandomizedGenState1(t *testing.T) { } for _, tt := range tests { - tt := tt - require.Panicsf(t, func() { simulation.RandomizedGenState(&tt.simState) }, tt.panicMsg) } } diff --git a/x/distribution/simulation/msg_factory.go b/x/distribution/simulation/msg_factory.go new file mode 100644 index 000000000000..2a494dd90c31 --- /dev/null +++ b/x/distribution/simulation/msg_factory.go @@ -0,0 +1,125 @@ +package simulation + +import ( + "context" + "errors" + + "cosmossdk.io/collections" + sdkmath "cosmossdk.io/math" + "cosmossdk.io/x/distribution/keeper" + "cosmossdk.io/x/distribution/types" + + "github.com/cosmos/cosmos-sdk/simsx" +) + +func MsgSetWithdrawAddressFactory(k keeper.Keeper) simsx.SimMsgFactoryFn[*types.MsgSetWithdrawAddress] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgSetWithdrawAddress) { + switch enabled, err := k.GetWithdrawAddrEnabled(ctx); { + case err != nil: + reporter.Skip("error getting params") + return nil, nil + case !enabled: + reporter.Skip("withdrawal is not enabled") + return nil, nil + } + delegator := testData.AnyAccount(reporter) + withdrawer := testData.AnyAccount(reporter, simsx.ExcludeAccounts(delegator)) + msg := types.NewMsgSetWithdrawAddress(delegator.AddressBech32, withdrawer.AddressBech32) + return []simsx.SimAccount{delegator}, msg + } +} + +func MsgWithdrawDelegatorRewardFactory(k keeper.Keeper, sk types.StakingKeeper) simsx.SimMsgFactoryFn[*types.MsgWithdrawDelegatorReward] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgWithdrawDelegatorReward) { + delegator := testData.AnyAccount(reporter) + + delegations, err := sk.GetAllDelegatorDelegations(ctx, delegator.Address) + switch { + case err != nil: + reporter.Skipf("error getting delegations: %v", err) + return nil, nil + case len(delegations) == 0: + reporter.Skip("no delegations found") + return nil, nil + } + delegation := delegations[testData.Rand().Intn(len(delegations))] + + valAddr, err := sk.ValidatorAddressCodec().StringToBytes(delegation.GetValidatorAddr()) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + + var valOper string + switch validator, err := sk.Validator(ctx, valAddr); { + case err != nil: + reporter.Skip(err.Error()) + return nil, nil + case validator == nil: + reporter.Skipf("validator %s not found", delegation.GetValidatorAddr()) + return nil, nil + default: + valOper = validator.GetOperator() + } + // get outstanding rewards so we can first check if the withdrawable coins are sendable + outstanding, err := k.GetValidatorOutstandingRewardsCoins(ctx, valAddr) + if err != nil { + reporter.Skipf("get outstanding rewards: %v", err) + return nil, nil + } + + for _, v := range outstanding { + if !testData.IsSendEnabledDenom(v.Denom) { + reporter.Skipf("denom send not enabled: " + v.Denom) + return nil, nil + } + } + + msg := types.NewMsgWithdrawDelegatorReward(delegator.AddressBech32, valOper) + return []simsx.SimAccount{delegator}, msg + } +} + +func MsgWithdrawValidatorCommissionFactory(k keeper.Keeper, sk types.StakingKeeper) simsx.SimMsgFactoryFn[*types.MsgWithdrawValidatorCommission] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgWithdrawValidatorCommission) { + allVals, err := sk.GetAllValidators(ctx) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + val := simsx.OneOf(testData.Rand(), allVals) + valAddrBz, err := sk.ValidatorAddressCodec().StringToBytes(val.GetOperator()) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + + commission, err := k.ValidatorsAccumulatedCommission.Get(ctx, valAddrBz) + if err != nil && !errors.Is(err, collections.ErrNotFound) { + reporter.Skip(err.Error()) + return nil, nil + } + + if commission.Commission.IsZero() { + reporter.Skip("validator commission is zero") + return nil, nil + } + msg := types.NewMsgWithdrawValidatorCommission(val.GetOperator()) + valAccount := testData.GetAccountbyAccAddr(reporter, valAddrBz) + return []simsx.SimAccount{valAccount}, msg + } +} + +func MsgUpdateParamsFactory() simsx.SimMsgFactoryFn[*types.MsgUpdateParams] { + return func(_ context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgUpdateParams) { + r := testData.Rand() + params := types.DefaultParams() + params.CommunityTax = r.DecN(sdkmath.LegacyNewDec(1)) + params.WithdrawAddrEnabled = r.Intn(2) == 0 + + return nil, &types.MsgUpdateParams{ + Authority: testData.ModuleAccountAddress(reporter, "gov"), + Params: params, + } + } +} diff --git a/x/distribution/simulation/operations.go b/x/distribution/simulation/operations.go deleted file mode 100644 index 4b067cbe7174..000000000000 --- a/x/distribution/simulation/operations.go +++ /dev/null @@ -1,247 +0,0 @@ -package simulation - -import ( - "fmt" - "math/rand" - - "github.com/pkg/errors" - - "cosmossdk.io/collections" - "cosmossdk.io/x/distribution/keeper" - "cosmossdk.io/x/distribution/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/testutil" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - OpWeightMsgSetWithdrawAddress = "op_weight_msg_set_withdraw_address" - OpWeightMsgWithdrawDelegationReward = "op_weight_msg_withdraw_delegation_reward" - OpWeightMsgWithdrawValidatorCommission = "op_weight_msg_withdraw_validator_commission" - - DefaultWeightMsgSetWithdrawAddress int = 50 - DefaultWeightMsgWithdrawDelegationReward int = 50 - DefaultWeightMsgWithdrawValidatorCommission int = 50 -) - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - appParams simtypes.AppParams, - cdc codec.JSONCodec, - txConfig client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k keeper.Keeper, - sk types.StakingKeeper, -) simulation.WeightedOperations { - var weightMsgSetWithdrawAddress int - appParams.GetOrGenerate(OpWeightMsgSetWithdrawAddress, &weightMsgSetWithdrawAddress, nil, func(_ *rand.Rand) { - weightMsgSetWithdrawAddress = DefaultWeightMsgSetWithdrawAddress - }) - - var weightMsgWithdrawDelegationReward int - appParams.GetOrGenerate(OpWeightMsgWithdrawDelegationReward, &weightMsgWithdrawDelegationReward, nil, func(_ *rand.Rand) { - weightMsgWithdrawDelegationReward = DefaultWeightMsgWithdrawDelegationReward - }) - - var weightMsgWithdrawValidatorCommission int - appParams.GetOrGenerate(OpWeightMsgWithdrawValidatorCommission, &weightMsgWithdrawValidatorCommission, nil, func(_ *rand.Rand) { - weightMsgWithdrawValidatorCommission = DefaultWeightMsgWithdrawValidatorCommission - }) - - return simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgSetWithdrawAddress, - SimulateMsgSetWithdrawAddress(txConfig, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightMsgWithdrawDelegationReward, - SimulateMsgWithdrawDelegatorReward(txConfig, ak, bk, k, sk), - ), - simulation.NewWeightedOperation( - weightMsgWithdrawValidatorCommission, - SimulateMsgWithdrawValidatorCommission(txConfig, ak, bk, k, sk), - ), - } -} - -// SimulateMsgSetWithdrawAddress generates a MsgSetWithdrawAddress with random values. -func SimulateMsgSetWithdrawAddress(txConfig client.TxConfig, ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - isWithdrawAddrEnabled, err := k.GetWithdrawAddrEnabled(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgSetWithdrawAddress{}), "error getting params"), nil, err - } - - if !isWithdrawAddrEnabled { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgSetWithdrawAddress{}), "withdrawal is not enabled"), nil, nil - } - - simAccount, _ := simtypes.RandomAcc(r, accs) - simToAccount, _ := simtypes.RandomAcc(r, accs) - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - addr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgSetWithdrawAddress{}), "error converting delegator address"), nil, err - } - toAddr, err := ak.AddressCodec().BytesToString(simToAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgSetWithdrawAddress{}), "error converting withdraw address"), nil, err - } - - msg := types.NewMsgSetWithdrawAddress(addr, toAddr) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txConfig, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// SimulateMsgWithdrawDelegatorReward generates a MsgWithdrawDelegatorReward with random values. -func SimulateMsgWithdrawDelegatorReward(txConfig client.TxConfig, ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, sk types.StakingKeeper) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - simAccount, _ := simtypes.RandomAcc(r, accs) - delegations, err := sk.GetAllDelegatorDelegations(ctx, simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "error getting delegations"), nil, err - } - if len(delegations) == 0 { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "number of delegators equal 0"), nil, nil - } - - delegation := delegations[r.Intn(len(delegations))] - - delAddr, err := sk.ValidatorAddressCodec().StringToBytes(delegation.GetValidatorAddr()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "error converting validator address"), nil, err - } - validator, err := sk.Validator(ctx, delAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "error getting validator"), nil, err - } - if validator == nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "validator is nil"), nil, fmt.Errorf("validator %s not found", delegation.GetValidatorAddr()) - } - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - addr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "error converting delegator address"), nil, err - } - - msg := types.NewMsgWithdrawDelegatorReward(addr, validator.GetOperator()) - - // get outstanding rewards so we can first check if the withdrawable coins are sendable - outstanding, err := k.GetValidatorOutstandingRewardsCoins(ctx, sdk.ValAddress(delAddr)) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "error getting outstanding rewards"), nil, err - } - - for _, v := range outstanding { - if !bk.IsSendEnabledDenom(ctx, v.Denom) { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "denom send not enabled: "+v.Denom), nil, nil - } - } - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txConfig, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// SimulateMsgWithdrawValidatorCommission generates a MsgWithdrawValidatorCommission with random values. -func SimulateMsgWithdrawValidatorCommission(txConfig client.TxConfig, ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, sk types.StakingKeeper) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgWithdrawValidatorCommission{}) - - allVals, err := sk.GetAllValidators(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting all validators"), nil, err - } - - validator, ok := testutil.RandSliceElem(r, allVals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "random validator is not ok"), nil, nil - } - - valBz, err := sk.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error converting validator address"), nil, err - } - - commission, err := k.ValidatorsAccumulatedCommission.Get(ctx, valBz) - if err != nil && !errors.Is(err, collections.ErrNotFound) { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator commission"), nil, err - } - - if commission.Commission.IsZero() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator commission is zero"), nil, nil - } - - simAccount, found := simtypes.FindAccount(accs, sdk.AccAddress(valBz)) - if !found { - return simtypes.NoOpMsg(types.ModuleName, msgType, "could not find account"), nil, fmt.Errorf("validator %s not found", validator.GetOperator()) - } - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - msg := types.NewMsgWithdrawValidatorCommission(validator.GetOperator()) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txConfig, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} diff --git a/x/distribution/simulation/proposals.go b/x/distribution/simulation/proposals.go deleted file mode 100644 index 3d9dfe6bd900..000000000000 --- a/x/distribution/simulation/proposals.go +++ /dev/null @@ -1,53 +0,0 @@ -package simulation - -import ( - "context" - "math/rand" - - coreaddress "cosmossdk.io/core/address" - sdkmath "cosmossdk.io/math" - "cosmossdk.io/x/distribution/types" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - DefaultWeightMsgUpdateParams int = 50 - - OpWeightMsgUpdateParams = "op_weight_msg_update_params" -) - -// ProposalMsgs defines the module weighted proposals' contents -func ProposalMsgs() []simtypes.WeightedProposalMsg { - return []simtypes.WeightedProposalMsg{ - simulation.NewWeightedProposalMsgX( - OpWeightMsgUpdateParams, - DefaultWeightMsgUpdateParams, - SimulateMsgUpdateParams, - ), - } -} - -// SimulateMsgUpdateParams returns a random MsgUpdateParams -func SimulateMsgUpdateParams(_ context.Context, r *rand.Rand, _ []simtypes.Account, cdc coreaddress.Codec) (sdk.Msg, error) { - // use the default gov module account address as authority - var authority sdk.AccAddress = address.Module("gov") - - params := types.DefaultParams() - params.CommunityTax = simtypes.RandomDecAmount(r, sdkmath.LegacyNewDec(1)) - params.WithdrawAddrEnabled = r.Intn(2) == 0 - - authorityAddr, err := cdc.BytesToString(authority) - if err != nil { - return nil, err - } - - return &types.MsgUpdateParams{ - Authority: authorityAddr, - Params: params, - }, nil -} diff --git a/x/distribution/simulation/proposals_test.go b/x/distribution/simulation/proposals_test.go deleted file mode 100644 index ce792ea856e4..000000000000 --- a/x/distribution/simulation/proposals_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package simulation_test - -import ( - "context" - "math/rand" - "testing" - - "gotest.tools/v3/assert" - - sdkmath "cosmossdk.io/math" - "cosmossdk.io/x/distribution/simulation" - "cosmossdk.io/x/distribution/types" - - codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" -) - -func TestProposalMsgs(t *testing.T) { - // initialize parameters - s := rand.NewSource(1) - r := rand.New(s) - addressCodec := codectestutil.CodecOptions{}.GetAddressCodec() - accounts := simtypes.RandomAccounts(r, 3) - - // execute ProposalMsgs function - weightedProposalMsgs := simulation.ProposalMsgs() - assert.Assert(t, len(weightedProposalMsgs) == 1) - - w0 := weightedProposalMsgs[0] - - // tests w0 interface: - assert.Equal(t, simulation.OpWeightMsgUpdateParams, w0.AppParamsKey()) - assert.Equal(t, simulation.DefaultWeightMsgUpdateParams, w0.DefaultWeight()) - - msg, err := w0.MsgSimulatorFn()(context.Background(), r, accounts, addressCodec) - assert.NilError(t, err) - msgUpdateParams, ok := msg.(*types.MsgUpdateParams) - assert.Assert(t, ok) - - addr, err := addressCodec.BytesToString(sdk.AccAddress(address.Module("gov"))) - assert.NilError(t, err) - assert.Equal(t, addr, msgUpdateParams.Authority) - assert.DeepEqual(t, sdkmath.LegacyNewDec(0), msgUpdateParams.Params.CommunityTax) - assert.Equal(t, true, msgUpdateParams.Params.WithdrawAddrEnabled) -} diff --git a/x/distribution/types/params_internal_test.go b/x/distribution/types/params_internal_test.go index 92cffd78460b..21bfd0f1bf16 100644 --- a/x/distribution/types/params_internal_test.go +++ b/x/distribution/types/params_internal_test.go @@ -24,7 +24,6 @@ func Test_validateAuxFuncs(t *testing.T) { {"two dec", args{math.LegacyNewDec(2)}, true}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { require.Equal(t, tt.wantErr, validateCommunityTax(tt.args.i) != nil) }) diff --git a/x/epochs/go.mod b/x/epochs/go.mod index 577509b1f8f0..c98608000c94 100644 --- a/x/epochs/go.mod +++ b/x/epochs/go.mod @@ -5,7 +5,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 @@ -20,7 +20,7 @@ require ( google.golang.org/grpc v1.66.2 ) -require cosmossdk.io/schema v0.2.0 // indirect +require cosmossdk.io/schema v0.3.0 // indirect require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect @@ -117,7 +117,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/x/epochs/go.sum b/x/epochs/go.sum index 27af6ac5b1b3..4b8596484eb6 100644 --- a/x/epochs/go.sum +++ b/x/epochs/go.sum @@ -6,8 +6,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -402,8 +402,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/epochs/module.go b/x/epochs/module.go index 6930d82174a2..2fba7c0de141 100644 --- a/x/epochs/module.go +++ b/x/epochs/module.go @@ -125,8 +125,3 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[types.StoreKey] = simtypes.NewStoreDecoderFuncFromCollectionsSchema(am.keeper.Schema) } - -// WeightedOperations returns the all the gov module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return nil -} diff --git a/x/epochs/simulation/genesis.go b/x/epochs/simulation/genesis.go index c236faacbb8a..8aa17add5bbc 100644 --- a/x/epochs/simulation/genesis.go +++ b/x/epochs/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" "strconv" "time" @@ -37,10 +35,5 @@ func RandomizedGenState(simState *module.SimulationState) { Epochs: epochs, } - bz, err := json.MarshalIndent(&epochsGenesis, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated epochs parameters:\n%s\n", bz) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(&epochsGenesis) } diff --git a/x/evidence/go.mod b/x/evidence/go.mod index df39a5174060..91a0f9f66bf8 100644 --- a/x/evidence/go.mod +++ b/x/evidence/go.mod @@ -5,7 +5,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 @@ -28,7 +28,7 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/log v1.4.1 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -121,7 +121,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/x/evidence/go.sum b/x/evidence/go.sum index a658644fd79f..5b3cf3f73e5b 100644 --- a/x/evidence/go.sum +++ b/x/evidence/go.sum @@ -6,8 +6,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -402,8 +402,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/evidence/keeper/msg_server_test.go b/x/evidence/keeper/msg_server_test.go index 86ac3447dcaa..fdc3b78d3cbf 100644 --- a/x/evidence/keeper/msg_server_test.go +++ b/x/evidence/keeper/msg_server_test.go @@ -70,7 +70,6 @@ func (s *KeeperTestSuite) TestSubmitEvidence() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { _, err := s.msgServer.SubmitEvidence(s.ctx, tc.req) if tc.expErr { diff --git a/x/evidence/module.go b/x/evidence/module.go index 513563aec10d..0327a83915ef 100644 --- a/x/evidence/module.go +++ b/x/evidence/module.go @@ -152,8 +152,3 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[types.StoreKey] = simtypes.NewStoreDecoderFuncFromCollectionsSchema(am.keeper.Schema) } - -// WeightedOperations returns the all the gov module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return nil -} diff --git a/x/evidence/simulation/genesis.go b/x/evidence/simulation/genesis.go index 24b956274695..d4a329d203bb 100644 --- a/x/evidence/simulation/genesis.go +++ b/x/evidence/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" "cosmossdk.io/x/evidence/exported" @@ -28,10 +26,5 @@ func RandomizedGenState(simState *module.SimulationState) { evidenceGenesis := types.NewGenesisState(ev) - bz, err := json.MarshalIndent(&evidenceGenesis, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated %s parameters:\n%s\n", types.ModuleName, bz) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(evidenceGenesis) } diff --git a/x/evidence/types/evidence_test.go b/x/evidence/types/evidence_test.go index bfa20f82a98d..dd6b31056a70 100644 --- a/x/evidence/types/evidence_test.go +++ b/x/evidence/types/evidence_test.go @@ -70,7 +70,6 @@ func TestEquivocationValidateBasic(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { require.Equal(t, tc.expectErr, tc.e.ValidateBasic() != nil) }) diff --git a/x/feegrant/client/cli/tx_test.go b/x/feegrant/client/cli/tx_test.go index 0759d0752f71..2fcb4020185e 100644 --- a/x/feegrant/client/cli/tx_test.go +++ b/x/feegrant/client/cli/tx_test.go @@ -420,8 +420,6 @@ func (s *CLITestSuite) TestNewCmdFeeGrant() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { cmd := cli.NewCmdFeeGrant() out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) @@ -624,8 +622,6 @@ func (s *CLITestSuite) TestFilteredFeeAllowance() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { cmd := cli.NewCmdFeeGrant() out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) @@ -687,8 +683,6 @@ func (s *CLITestSuite) TestFilteredFeeAllowance() { } for _, tc := range cases { - tc := tc - s.Run(tc.name, func() { err := tc.malleate() s.Require().NoError(err) diff --git a/x/feegrant/go.mod b/x/feegrant/go.mod index 6ce3c7e54836..9245134a41a2 100644 --- a/x/feegrant/go.mod +++ b/x/feegrant/go.mod @@ -5,7 +5,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 @@ -37,7 +37,7 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/log v1.4.1 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -129,7 +129,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/x/feegrant/go.sum b/x/feegrant/go.sum index 59aa48e27918..4a17d71081d5 100644 --- a/x/feegrant/go.sum +++ b/x/feegrant/go.sum @@ -4,8 +4,8 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +14,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 h1:XQJj9Dv9Gtze0l2TF79BU5lkP6MkUveTUuKICmxoz+o= cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190/go.mod h1:7WUGupOvmlHJoIMBz1JbObQxeo6/TDiuDBxmtod8HRg= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= @@ -410,8 +410,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/feegrant/grant_test.go b/x/feegrant/grant_test.go index a333a51e7756..4880b6eb3cf0 100644 --- a/x/feegrant/grant_test.go +++ b/x/feegrant/grant_test.go @@ -81,7 +81,6 @@ func TestGrant(t *testing.T) { } for name, tc := range cases { - tc := tc t.Run(name, func(t *testing.T) { granterStr, err := addressCodec.BytesToString(tc.granter) require.NoError(t, err) diff --git a/x/feegrant/keeper/genesis_test.go b/x/feegrant/keeper/genesis_test.go index 61cb5cd14a0c..dd2a1eb27bfc 100644 --- a/x/feegrant/keeper/genesis_test.go +++ b/x/feegrant/keeper/genesis_test.go @@ -144,7 +144,6 @@ func TestInitGenesis(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { f := initFixture(t) if !tc.invalidAddr { diff --git a/x/feegrant/module/depinject.go b/x/feegrant/module/depinject.go index 018b09d3d593..613d51a14743 100644 --- a/x/feegrant/module/depinject.go +++ b/x/feegrant/module/depinject.go @@ -7,9 +7,13 @@ import ( "cosmossdk.io/depinject/appconfig" "cosmossdk.io/x/feegrant" "cosmossdk.io/x/feegrant/keeper" + "cosmossdk.io/x/feegrant/simulation" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/simsx" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) var _ depinject.OnePerModuleType = AppModule{} @@ -35,6 +39,23 @@ type FeegrantInputs struct { func ProvideModule(in FeegrantInputs) (keeper.Keeper, appmodule.AppModule) { k := keeper.NewKeeper(in.Environment, in.Cdc, in.AccountKeeper) - m := NewAppModule(in.Cdc, in.AccountKeeper, in.BankKeeper, k, in.Registry) + m := NewAppModule(in.Cdc, k, in.Registry) return k, m } + +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenState of the feegrant module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + simulation.RandomizedGenState(simState) +} + +// RegisterStoreDecoder registers a decoder for feegrant module's types +func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { + sdr[feegrant.StoreKey] = simulation.NewDecodeStore(am.cdc) +} + +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_grant_fee_allowance", 100), simulation.MsgGrantAllowanceFactory(am.keeper)) + reg.Add(weights.Get("msg_grant_revoke_allowance", 100), simulation.MsgRevokeAllowanceFactory(am.keeper)) +} diff --git a/x/feegrant/module/module.go b/x/feegrant/module/module.go index c6c79fa396e3..2e22fef937bc 100644 --- a/x/feegrant/module/module.go +++ b/x/feegrant/module/module.go @@ -15,13 +15,11 @@ import ( "cosmossdk.io/x/feegrant" "cosmossdk.io/x/feegrant/client/cli" "cosmossdk.io/x/feegrant/keeper" - "cosmossdk.io/x/feegrant/simulation" sdkclient "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/types/module" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) var ( @@ -41,19 +39,15 @@ type AppModule struct { cdc codec.Codec registry cdctypes.InterfaceRegistry - keeper keeper.Keeper - accountKeeper feegrant.AccountKeeper - bankKeeper feegrant.BankKeeper + keeper keeper.Keeper } // NewAppModule creates a new AppModule object -func NewAppModule(cdc codec.Codec, ak feegrant.AccountKeeper, bk feegrant.BankKeeper, keeper keeper.Keeper, registry cdctypes.InterfaceRegistry) AppModule { +func NewAppModule(cdc codec.Codec, keeper keeper.Keeper, registry cdctypes.InterfaceRegistry) AppModule { return AppModule{ - cdc: cdc, - keeper: keeper, - accountKeeper: ak, - bankKeeper: bk, - registry: registry, + cdc: cdc, + keeper: keeper, + registry: registry, } } @@ -153,23 +147,3 @@ func (AppModule) ConsensusVersion() uint64 { return 2 } func (am AppModule) EndBlock(ctx context.Context) error { return EndBlocker(ctx, am.keeper) } - -// AppModuleSimulation functions - -// GenerateGenesisState creates a randomized GenState of the feegrant module. -func (AppModule) GenerateGenesisState(simState *module.SimulationState) { - simulation.RandomizedGenState(simState) -} - -// RegisterStoreDecoder registers a decoder for feegrant module's types -func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { - sdr[feegrant.StoreKey] = simulation.NewDecodeStore(am.cdc) -} - -// WeightedOperations returns all the feegrant module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - simState.AppParams, simState.TxConfig, - am.accountKeeper, am.bankKeeper, am.keeper, - ) -} diff --git a/x/feegrant/simulation/decoder_test.go b/x/feegrant/simulation/decoder_test.go index f29fa98977ad..03d7d1a674c2 100644 --- a/x/feegrant/simulation/decoder_test.go +++ b/x/feegrant/simulation/decoder_test.go @@ -61,7 +61,6 @@ func TestDecodeStore(t *testing.T) { } for i, tt := range tests { - i, tt := i, tt t.Run(tt.name, func(t *testing.T) { switch i { case len(tests) - 1: diff --git a/x/feegrant/simulation/msg_factory.go b/x/feegrant/simulation/msg_factory.go new file mode 100644 index 000000000000..fd8bacb88745 --- /dev/null +++ b/x/feegrant/simulation/msg_factory.go @@ -0,0 +1,58 @@ +package simulation + +import ( + "context" + + "cosmossdk.io/x/feegrant" + "cosmossdk.io/x/feegrant/keeper" + + "github.com/cosmos/cosmos-sdk/simsx" +) + +func MsgGrantAllowanceFactory(k keeper.Keeper) simsx.SimMsgFactoryFn[*feegrant.MsgGrantAllowance] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *feegrant.MsgGrantAllowance) { + granter := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + grantee := testData.AnyAccount(reporter, simsx.ExcludeAccounts(granter)) + if reporter.IsSkipped() { + return nil, nil + } + if f, _ := k.GetAllowance(ctx, granter.Address, grantee.Address); f != nil { + reporter.Skip("fee allowance exists") + return nil, nil + } + + coins := granter.LiquidBalance().RandSubsetCoins(reporter, simsx.WithSendEnabledCoins()) + oneYear := simsx.BlockTime(ctx).AddDate(1, 0, 0) + msg, err := feegrant.NewMsgGrantAllowance( + &feegrant.BasicAllowance{SpendLimit: coins, Expiration: &oneYear}, + granter.AddressBech32, + grantee.AddressBech32, + ) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + return []simsx.SimAccount{granter}, msg + } +} + +func MsgRevokeAllowanceFactory(k keeper.Keeper) simsx.SimMsgFactoryFn[*feegrant.MsgRevokeAllowance] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *feegrant.MsgRevokeAllowance) { + var gotGrant *feegrant.Grant + if err := k.IterateAllFeeAllowances(ctx, func(grant feegrant.Grant) bool { + gotGrant = &grant + return true + }); err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + if gotGrant == nil { + reporter.Skip("no grant found") + return nil, nil + } + granter := testData.GetAccount(reporter, gotGrant.Granter) + grantee := testData.GetAccount(reporter, gotGrant.Grantee) + msg := feegrant.NewMsgRevokeAllowance(granter.AddressBech32, grantee.AddressBech32) + return []simsx.SimAccount{granter}, &msg + } +} diff --git a/x/feegrant/simulation/operations.go b/x/feegrant/simulation/operations.go deleted file mode 100644 index 65bd53d528e9..000000000000 --- a/x/feegrant/simulation/operations.go +++ /dev/null @@ -1,197 +0,0 @@ -package simulation - -import ( - "math/rand" - - "cosmossdk.io/x/feegrant" - "cosmossdk.io/x/feegrant/keeper" - - "github.com/cosmos/cosmos-sdk/client" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - OpWeightMsgGrantAllowance = "op_weight_msg_grant_fee_allowance" - OpWeightMsgRevokeAllowance = "op_weight_msg_grant_revoke_allowance" - DefaultWeightGrantAllowance int = 100 - DefaultWeightRevokeAllowance int = 100 -) - -var ( - TypeMsgGrantAllowance = sdk.MsgTypeURL(&feegrant.MsgGrantAllowance{}) - TypeMsgRevokeAllowance = sdk.MsgTypeURL(&feegrant.MsgRevokeAllowance{}) -) - -func WeightedOperations( - appParams simtypes.AppParams, - txConfig client.TxConfig, - ak feegrant.AccountKeeper, - bk feegrant.BankKeeper, - k keeper.Keeper, -) simulation.WeightedOperations { - var ( - weightMsgGrantAllowance int - weightMsgRevokeAllowance int - ) - - appParams.GetOrGenerate(OpWeightMsgGrantAllowance, &weightMsgGrantAllowance, nil, - func(_ *rand.Rand) { - weightMsgGrantAllowance = DefaultWeightGrantAllowance - }, - ) - - appParams.GetOrGenerate(OpWeightMsgRevokeAllowance, &weightMsgRevokeAllowance, nil, - func(_ *rand.Rand) { - weightMsgRevokeAllowance = DefaultWeightRevokeAllowance - }, - ) - - return simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgGrantAllowance, - SimulateMsgGrantAllowance(txConfig, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightMsgRevokeAllowance, - SimulateMsgRevokeAllowance(txConfig, ak, bk, k), - ), - } -} - -// SimulateMsgGrantAllowance generates MsgGrantAllowance with random values. -func SimulateMsgGrantAllowance( - txConfig client.TxConfig, - ak feegrant.AccountKeeper, - bk feegrant.BankKeeper, - k keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - granter, _ := simtypes.RandomAcc(r, accs) - grantee, _ := simtypes.RandomAcc(r, accs) - granterStr, err := ak.AddressCodec().BytesToString(granter.Address) - if err != nil { - return simtypes.OperationMsg{}, nil, err - } - granteeStr, err := ak.AddressCodec().BytesToString(grantee.Address) - if err != nil { - return simtypes.OperationMsg{}, nil, err - } - - if granteeStr == granterStr { - return simtypes.NoOpMsg(feegrant.ModuleName, TypeMsgGrantAllowance, "grantee and granter cannot be same"), nil, nil - } - - if f, _ := k.GetAllowance(ctx, granter.Address, grantee.Address); f != nil { - return simtypes.NoOpMsg(feegrant.ModuleName, TypeMsgGrantAllowance, "fee allowance exists"), nil, nil - } - - account := ak.GetAccount(ctx, granter.Address) - - spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) - if spendableCoins.Empty() { - return simtypes.NoOpMsg(feegrant.ModuleName, TypeMsgGrantAllowance, "unable to grant empty coins as SpendLimit"), nil, nil - } - - oneYear := ctx.HeaderInfo().Time.AddDate(1, 0, 0) - msg, err := feegrant.NewMsgGrantAllowance(&feegrant.BasicAllowance{ - SpendLimit: spendableCoins, - Expiration: &oneYear, - }, granterStr, granteeStr) - if err != nil { - return simtypes.NoOpMsg(feegrant.ModuleName, TypeMsgGrantAllowance, err.Error()), nil, err - } - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txConfig, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: granter, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: feegrant.ModuleName, - CoinsSpentInMsg: spendableCoins, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// SimulateMsgRevokeAllowance generates a MsgRevokeAllowance with random values. -func SimulateMsgRevokeAllowance( - txConfig client.TxConfig, - ak feegrant.AccountKeeper, - bk feegrant.BankKeeper, - k keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - hasGrant := false - - var granterAddr sdk.AccAddress - var granteeAddr sdk.AccAddress - err := k.IterateAllFeeAllowances(ctx, func(grant feegrant.Grant) bool { - granter, err := ak.AddressCodec().StringToBytes(grant.Granter) - if err != nil { - panic(err) - } - grantee, err := ak.AddressCodec().StringToBytes(grant.Grantee) - if err != nil { - panic(err) - } - granterAddr = granter - granteeAddr = grantee - hasGrant = true - return true - }) - if err != nil { - return simtypes.OperationMsg{}, nil, err - } - - if !hasGrant { - return simtypes.NoOpMsg(feegrant.ModuleName, TypeMsgRevokeAllowance, "no grants"), nil, nil - } - granter, ok := simtypes.FindAccount(accs, granterAddr) - - if !ok { - return simtypes.NoOpMsg(feegrant.ModuleName, TypeMsgRevokeAllowance, "Account not found"), nil, nil - } - - account := ak.GetAccount(ctx, granter.Address) - spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) - - granterStr, err := ak.AddressCodec().BytesToString(granterAddr) - if err != nil { - return simtypes.NoOpMsg(feegrant.ModuleName, TypeMsgRevokeAllowance, err.Error()), nil, err - } - granteeStr, err := ak.AddressCodec().BytesToString(granteeAddr) - if err != nil { - return simtypes.NoOpMsg(feegrant.ModuleName, TypeMsgRevokeAllowance, err.Error()), nil, err - } - msg := feegrant.NewMsgRevokeAllowance(granterStr, granteeStr) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txConfig, - Cdc: nil, - Msg: &msg, - Context: ctx, - SimAccount: granter, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: feegrant.ModuleName, - CoinsSpentInMsg: spendableCoins, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} diff --git a/x/genutil/client/cli/gentx_test.go b/x/genutil/client/cli/gentx_test.go index 221ce645da43..f3cd97a01844 100644 --- a/x/genutil/client/cli/gentx_test.go +++ b/x/genutil/client/cli/gentx_test.go @@ -109,7 +109,6 @@ func (s *CLITestSuite) TestGenTxCmd() { } for _, tc := range tests { - tc := tc dir := s.T().TempDir() genTxFile := filepath.Join(dir, "myTx") diff --git a/x/genutil/client/cli/migrate_test.go b/x/genutil/client/cli/migrate_test.go index 7e84b491b132..5cd7485d441c 100644 --- a/x/genutil/client/cli/migrate_test.go +++ b/x/genutil/client/cli/migrate_test.go @@ -50,7 +50,6 @@ func TestMigrateGenesis(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { genesisFile := testutil.WriteToNewTempFile(t, tc.genesis) jsonOutput, err := clitestutil.ExecTestCLICmd( diff --git a/x/genutil/client/cli/validate_genesis_test.go b/x/genutil/client/cli/validate_genesis_test.go index 2608f448d54b..41c337f13732 100644 --- a/x/genutil/client/cli/validate_genesis_test.go +++ b/x/genutil/client/cli/validate_genesis_test.go @@ -62,7 +62,7 @@ func TestValidateGenesis(t *testing.T) { }(), "section is missing in the app_state", module.NewManagerFromMap(map[string]appmodulev2.AppModule{ - "custommod": staking.NewAppModule(cdc, nil, nil, nil), + "custommod": staking.NewAppModule(cdc, nil), }), }, { @@ -85,8 +85,6 @@ func TestValidateGenesis(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { genesisFile := testutil.WriteToNewTempFile(t, tc.genesis) _, err := clitestutil.ExecTestCLICmd(client.Context{}, cli.ValidateGenesisCmd(tc.genMM), []string{genesisFile.Name()}) diff --git a/x/genutil/utils_test.go b/x/genutil/utils_test.go index af2963df41fd..8304c290e647 100644 --- a/x/genutil/utils_test.go +++ b/x/genutil/utils_test.go @@ -51,7 +51,6 @@ func TestInitializeNodeValidatorFilesFromMnemonic(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { _, _, err := InitializeNodeValidatorFilesFromMnemonic(cfg, tt.mnemonic, "ed25519") diff --git a/x/gov/client/cli/prompt_test.go b/x/gov/client/cli/prompt_test.go index 89110536d7e1..359c9dea5b53 100644 --- a/x/gov/client/cli/prompt_test.go +++ b/x/gov/client/cli/prompt_test.go @@ -72,7 +72,6 @@ func TestPromptParseInteger(t *testing.T) { } for _, tc := range values { - tc := tc t.Run(tc.in, func(t *testing.T) { origStdin := readline.Stdin defer func() { diff --git a/x/gov/client/cli/tx_test.go b/x/gov/client/cli/tx_test.go index f0933d9ebedd..9bb1eddc19d5 100644 --- a/x/gov/client/cli/tx_test.go +++ b/x/gov/client/cli/tx_test.go @@ -160,8 +160,6 @@ func (s *CLITestSuite) TestNewCmdSubmitProposal() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { cmd := cli.NewCmdSubmitProposal() @@ -256,8 +254,6 @@ func (s *CLITestSuite) TestNewCmdSubmitLegacyProposal() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { cmd := cli.NewCmdSubmitLegacyProposal() @@ -360,7 +356,6 @@ func (s *CLITestSuite) TestNewCmdWeightedVote() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := cli.NewCmdWeightedVote() out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) diff --git a/x/gov/client/utils/query_test.go b/x/gov/client/utils/query_test.go index 1d1b4119915a..3f555f37d90c 100644 --- a/x/gov/client/utils/query_test.go +++ b/x/gov/client/utils/query_test.go @@ -193,8 +193,6 @@ func TestGetPaginatedVotes(t *testing.T) { }, }, } { - tc := tc - t.Run(tc.description, func(t *testing.T) { marshaled := make([][]byte, len(tc.msgs)) clientCtx := client.Context{}. @@ -298,8 +296,6 @@ func TestGetSingleVote(t *testing.T) { }, }, } { - tc := tc - t.Run(tc.description, func(t *testing.T) { marshaled := make([][]byte, len(tc.msgs)) clientCtx := client.Context{}. diff --git a/x/gov/go.mod b/x/gov/go.mod index cf006f093661..01075c222568 100644 --- a/x/gov/go.mod +++ b/x/gov/go.mod @@ -5,7 +5,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 @@ -30,13 +30,14 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 google.golang.org/grpc v1.66.2 google.golang.org/protobuf v1.34.2 - gotest.tools/v3 v3.5.1 ) +require gotest.tools/v3 v3.5.1 // indirect + require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/x/tx v0.13.3 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect @@ -126,7 +127,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/x/gov/go.sum b/x/gov/go.sum index 0fbe110c42af..ee4a25f22369 100644 --- a/x/gov/go.sum +++ b/x/gov/go.sum @@ -4,8 +4,8 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +14,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -408,8 +408,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/gov/keeper/grpc_query_test.go b/x/gov/keeper/grpc_query_test.go index 0d90df884de6..265726a7f75a 100644 --- a/x/gov/keeper/grpc_query_test.go +++ b/x/gov/keeper/grpc_query_test.go @@ -938,8 +938,6 @@ func (suite *KeeperTestSuite) TestGRPCQueryParams() { } for _, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { params, err := queryClient.Params(gocontext.Background(), &tc.req) @@ -1008,7 +1006,6 @@ func (suite *KeeperTestSuite) TestGRPCQueryMessagedBasedParams() { } for _, tc := range testCases { - tc := tc suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { params, err := queryClient.MessageBasedParams(suite.ctx, &tc.req) if tc.expErrMsg != "" { diff --git a/x/gov/keeper/msg_server_test.go b/x/gov/keeper/msg_server_test.go index a1460167f227..34d01824d97f 100644 --- a/x/gov/keeper/msg_server_test.go +++ b/x/gov/keeper/msg_server_test.go @@ -2008,7 +2008,6 @@ func (suite *KeeperTestSuite) TestMsgUpdateParams() { } for _, tc := range testCases { - tc := tc suite.Run(tc.name, func() { msg := tc.input() exec := func(updateParams *v1.MsgUpdateParams) error { @@ -2154,7 +2153,6 @@ func (suite *KeeperTestSuite) TestMsgUpdateMessageParams() { } for _, tc := range testCases { - tc := tc suite.Run(tc.name, func() { _, err := suite.msgSrvr.UpdateMessageParams(suite.ctx, tc.input) if tc.expErrMsg != "" { @@ -2308,7 +2306,6 @@ func (suite *KeeperTestSuite) TestMsgSudoExec() { } for _, tc := range testCases { - tc := tc suite.Run(tc.name, func() { _, err := suite.msgSrvr.SudoExec(suite.ctx, tc.input) if tc.expErrMsg != "" { diff --git a/x/gov/migrations/v3/convert_test.go b/x/gov/migrations/v3/convert_test.go index 3b44f9724552..ff93e5474873 100644 --- a/x/gov/migrations/v3/convert_test.go +++ b/x/gov/migrations/v3/convert_test.go @@ -49,7 +49,6 @@ func TestConvertToLegacyProposal(t *testing.T) { for name, tc := range testCases { t.Run(name, func(t *testing.T) { - tc := tc proposal.FinalTallyResult = &tc.tallyResult v1beta1Proposal, err := v3.ConvertToLegacyProposal(proposal) if tc.expErr { @@ -156,8 +155,6 @@ func TestConvertToLegacyTallyResult(t *testing.T) { }, } for name, tc := range testCases { - tc := tc - t.Run(name, func(t *testing.T) { _, err := v3.ConvertToLegacyTallyResult(&tc.tallyResult) if tc.expErr { diff --git a/x/gov/module.go b/x/gov/module.go index 01a66ef07b1d..8fc5f3061aab 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -21,6 +21,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simsx" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" @@ -209,27 +210,32 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { simulation.RandomizedGenState(simState) } -// ProposalContents returns all the gov content functions used to -// simulate governance proposals. -func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent { //nolint:staticcheck // used for legacy testing - return simulation.ProposalContents() -} - -// ProposalMsgs returns all the gov msgs used to simulate governance proposals. -func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { - return simulation.ProposalMsgs() -} - // RegisterStoreDecoder registers a decoder for gov module's types func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[govtypes.StoreKey] = simtypes.NewStoreDecoderFuncFromCollectionsSchema(am.keeper.Schema) } -// WeightedOperations returns the all the gov module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - simState.AppParams, simState.TxConfig, - am.accountKeeper, am.bankKeeper, am.keeper, - simState.ProposalMsgs, simState.LegacyProposalContents, - ) +// ProposalMsgsX returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("submit_text_proposal", 5), simulation.TextProposalFactory()) +} + +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry, proposalMsgIter simsx.WeightedProposalMsgIter, + legacyProposals []simtypes.WeightedProposalContent, //nolint:staticcheck // used for legacy proposal types +) { + // submit proposal for each payload message + for weight, factory := range proposalMsgIter { + // use a ratio so that we don't flood with gov ops + reg.Add(weight/25, simulation.MsgSubmitProposalFactory(am.keeper, factory)) + } + for _, wContent := range legacyProposals { + reg.Add(weights.Get(wContent.AppParamsKey(), uint32(wContent.DefaultWeight())), simulation.MsgSubmitLegacyProposalFactory(am.keeper, wContent.ContentSimulatorFn())) + } + + state := simulation.NewSharedState() + reg.Add(weights.Get("msg_deposit", 100), simulation.MsgDepositFactory(am.keeper, state)) + reg.Add(weights.Get("msg_vote", 67), simulation.MsgVoteFactory(am.keeper, state)) + reg.Add(weights.Get("msg_weighted_vote", 33), simulation.MsgWeightedVoteFactory(am.keeper, state)) + reg.Add(weights.Get("cancel_proposal", 5), simulation.MsgCancelProposalFactory(am.keeper, state)) + reg.Add(weights.Get("legacy_text_proposal", 5), simulation.MsgSubmitLegacyProposalFactory(am.keeper, simulation.SimulateLegacyTextProposalContent)) } diff --git a/x/gov/simulation/genesis.go b/x/gov/simulation/genesis.go index a522593a2b96..26f7bdafa6f9 100644 --- a/x/gov/simulation/genesis.go +++ b/x/gov/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" "time" @@ -198,10 +196,5 @@ func RandomizedGenState(simState *module.SimulationState) { ), ) - bz, err := json.MarshalIndent(&govGenesis, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated governance parameters:\n%s\n", bz) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(govGenesis) } diff --git a/x/gov/simulation/genesis_test.go b/x/gov/simulation/genesis_test.go index 215225085d3a..4f5e70312ff7 100644 --- a/x/gov/simulation/genesis_test.go +++ b/x/gov/simulation/genesis_test.go @@ -100,8 +100,6 @@ func TestRandomizedGenState1(t *testing.T) { } for _, tt := range tests { - tt := tt - require.Panicsf(t, func() { simulation.RandomizedGenState(&tt.simState) }, tt.panicMsg) } } diff --git a/x/gov/simulation/msg_factory.go b/x/gov/simulation/msg_factory.go new file mode 100644 index 000000000000..b1267a9ea262 --- /dev/null +++ b/x/gov/simulation/msg_factory.go @@ -0,0 +1,371 @@ +package simulation + +import ( + "context" + "math" + "math/rand" + "sync/atomic" + "time" + + sdkmath "cosmossdk.io/math" + "cosmossdk.io/x/gov/keeper" + v1 "cosmossdk.io/x/gov/types/v1" + + "github.com/cosmos/cosmos-sdk/simsx" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" +) + +func MsgDepositFactory(k *keeper.Keeper, sharedState *SharedState) simsx.SimMsgFactoryFn[*v1.MsgDeposit] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *v1.MsgDeposit) { + r := testData.Rand() + proposalID, ok := randomProposalID(r, k, ctx, v1.StatusDepositPeriod, sharedState) + if !ok { + reporter.Skip("no proposal in deposit state") + return nil, nil + } + proposal, err := k.Proposals.Get(ctx, proposalID) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + // calculate deposit amount + deposit := randDeposit(ctx, proposal, k, r, reporter) + if reporter.IsSkipped() { + return nil, nil + } + from := testData.AnyAccount(reporter, simsx.WithLiquidBalanceGTE(deposit)) + return []simsx.SimAccount{from}, v1.NewMsgDeposit(from.AddressBech32, proposalID, sdk.NewCoins(deposit)) + } +} + +func MsgVoteFactory(k *keeper.Keeper, sharedState *SharedState) simsx.SimMsgFactoryFn[*v1.MsgVote] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *v1.MsgVote) { + r := testData.Rand() + proposalID, ok := randomProposalID(r, k, ctx, v1.StatusVotingPeriod, sharedState) + if !ok { + reporter.Skip("no proposal in deposit state") + return nil, nil + } + from := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + msg := v1.NewMsgVote(from.AddressBech32, proposalID, randomVotingOption(r.Rand), "") + return []simsx.SimAccount{from}, msg + } +} + +func MsgWeightedVoteFactory(k *keeper.Keeper, sharedState *SharedState) simsx.SimMsgFactoryFn[*v1.MsgVoteWeighted] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *v1.MsgVoteWeighted) { + r := testData.Rand() + proposalID, ok := randomProposalID(r, k, ctx, v1.StatusVotingPeriod, sharedState) + if !ok { + reporter.Skip("no proposal in deposit state") + return nil, nil + } + from := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + msg := v1.NewMsgVoteWeighted(from.AddressBech32, proposalID, randomWeightedVotingOptions(r.Rand), "") + return []simsx.SimAccount{from}, msg + } +} + +func MsgCancelProposalFactory(k *keeper.Keeper, sharedState *SharedState) simsx.SimMsgFactoryFn[*v1.MsgCancelProposal] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *v1.MsgCancelProposal) { + r := testData.Rand() + status := simsx.OneOf(r, []v1.ProposalStatus{v1.StatusDepositPeriod, v1.StatusVotingPeriod}) + proposalID, ok := randomProposalID(r, k, ctx, status, sharedState) + if !ok { + reporter.Skip("no proposal in deposit state") + return nil, nil + } + proposal, err := k.Proposals.Get(ctx, proposalID) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + // is cancellable? copied from keeper + maxCancelPeriodRate := sdkmath.LegacyMustNewDecFromStr(must(k.Params.Get(ctx)).ProposalCancelMaxPeriod) + maxCancelPeriod := time.Duration(float64(proposal.VotingEndTime.Sub(*proposal.VotingStartTime)) * maxCancelPeriodRate.MustFloat64()).Round(time.Second) + if proposal.VotingEndTime.Add(-maxCancelPeriod).Before(simsx.BlockTime(ctx)) { + reporter.Skip("not cancellable anymore") + return nil, nil + } + + from := testData.GetAccount(reporter, proposal.Proposer) + if from.LiquidBalance().Empty() { + reporter.Skip("proposer is broke") + return nil, nil + } + msg := v1.NewMsgCancelProposal(proposalID, from.AddressBech32) + return []simsx.SimAccount{from}, msg + } +} + +func MsgSubmitLegacyProposalFactory(k *keeper.Keeper, contentSimFn simtypes.ContentSimulatorFn) simsx.SimMsgFactoryX { //nolint:staticcheck // used for legacy testing + return simsx.NewSimMsgFactoryWithFutureOps[*v1.MsgSubmitProposal](func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter, fOpsReg simsx.FutureOpsRegistry) ([]simsx.SimAccount, *v1.MsgSubmitProposal) { + // 1) submit proposal now + accs := testData.AllAccounts() + content := contentSimFn(testData.Rand().Rand, ctx, accs) + if content == nil { + reporter.Skip("content is nil") + return nil, nil + } + govacc := must(testData.AddressCodec().BytesToString(k.GetGovernanceAccount(ctx).GetAddress())) + contentMsg := must(v1.NewLegacyContent(content, govacc)) + return submitProposalWithVotesScheduled(ctx, k, testData, reporter, fOpsReg, contentMsg) + }) +} + +func MsgSubmitProposalFactory(k *keeper.Keeper, payloadFactory simsx.FactoryMethod) simsx.SimMsgFactoryX { + return simsx.NewSimMsgFactoryWithFutureOps[*v1.MsgSubmitProposal](func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter, fOpsReg simsx.FutureOpsRegistry) ([]simsx.SimAccount, *v1.MsgSubmitProposal) { + _, proposalMsg := payloadFactory(ctx, testData, reporter) + return submitProposalWithVotesScheduled(ctx, k, testData, reporter, fOpsReg, proposalMsg) + }) +} + +func submitProposalWithVotesScheduled( + ctx context.Context, + k *keeper.Keeper, + testData *simsx.ChainDataSource, + reporter simsx.SimulationReporter, + fOpsReg simsx.FutureOpsRegistry, + proposalMsgs ...sdk.Msg, +) ([]simsx.SimAccount, *v1.MsgSubmitProposal) { + r := testData.Rand() + expedited := true + // expedited := r.Bool() + params := must(k.Params.Get(ctx)) + minDeposits := params.MinDeposit + if expedited { + minDeposits = params.ExpeditedMinDeposit + } + minDeposit := r.Coin(minDeposits) + + minDepositRatio := must(sdkmath.LegacyNewDecFromStr(params.GetMinDepositRatio())) + threshold := minDeposit.Amount.ToLegacyDec().Mul(minDepositRatio).TruncateInt() + + minDepositPercent := must(sdkmath.LegacyNewDecFromStr(params.MinInitialDepositRatio)) + minAmount := sdkmath.LegacyNewDecFromInt(minDeposit.Amount).Mul(minDepositPercent).TruncateInt() + amount, err := r.PositiveSDKIntn(minDeposit.Amount.Sub(minAmount)) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + if amount.LT(threshold) { + reporter.Skip("below threshold amount for proposal") + return nil, nil + } + deposit := minDeposit + // deposit := sdk.Coin{Amount: amount.Add(minAmount), Denom: minDeposit.Denom} + + proposer := testData.AnyAccount(reporter, simsx.WithLiquidBalanceGTE(deposit)) + if reporter.IsSkipped() || !proposer.LiquidBalance().BlockAmount(deposit) { + return nil, nil + } + proposalType := v1.ProposalType_PROPOSAL_TYPE_STANDARD + if expedited { + proposalType = v1.ProposalType_PROPOSAL_TYPE_EXPEDITED + } + msg, err := v1.NewMsgSubmitProposal( + proposalMsgs, + sdk.Coins{deposit}, + proposer.AddressBech32, + r.StringN(100), + r.StringN(100), + r.StringN(100), + proposalType, + ) + if err != nil { + reporter.Skip("unable to generate a submit proposal msg") + return nil, nil + } + // futureOps + var ( + // The states are: + // column 1: All validators vote + // column 2: 90% vote + // column 3: 75% vote + // column 4: 40% vote + // column 5: 15% vote + // column 6: no one votes + // All columns sum to 100 for simplicity, values chosen by @valardragon semi-arbitrarily, + // feel free to change. + numVotesTransitionMatrix = must(simulation.CreateTransitionMatrix([][]int{ + {20, 10, 0, 0, 0, 0}, + {55, 50, 20, 10, 0, 0}, + {25, 25, 30, 25, 30, 15}, + {0, 15, 30, 25, 30, 30}, + {0, 0, 20, 30, 30, 30}, + {0, 0, 0, 10, 10, 25}, + })) + statePercentageArray = []float64{1, .9, .75, .4, .15, 0} + curNumVotesState = 1 + ) + + // get the submitted proposal ID + proposalID := must(k.ProposalID.Peek(ctx)) + + // 2) Schedule operations for votes + // 2.1) first pick a number of people to vote. + curNumVotesState = numVotesTransitionMatrix.NextState(r.Rand, curNumVotesState) + numVotes := int(math.Ceil(float64(testData.AccountsCount()) * statePercentageArray[curNumVotesState])) + + // 2.2) select who votes and when + whoVotes := r.Perm(testData.AccountsCount()) + + // didntVote := whoVotes[numVotes:] + whoVotes = whoVotes[:numVotes] + votingPeriod := params.VotingPeriod + // future ops so that votes do not flood the sims. + if r.Intn(100) == 1 { // 1% chance + now := simsx.BlockTime(ctx) + for i := 0; i < numVotes; i++ { + var vF simsx.SimMsgFactoryFn[*v1.MsgVote] = func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *v1.MsgVote) { + switch p, err := k.Proposals.Get(ctx, proposalID); { + case err != nil: + reporter.Skip(err.Error()) + return nil, nil + case p.Status != v1.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD: + reporter.Skip("proposal not in voting period") + return nil, nil + } + voter := testData.AccountAt(reporter, whoVotes[i]) + msg := v1.NewMsgVote(voter.AddressBech32, proposalID, randomVotingOption(r.Rand), "") + return []simsx.SimAccount{voter}, msg + } + whenVote := now.Add(time.Duration(r.Int63n(int64(votingPeriod.Seconds()))) * time.Second) + fOpsReg.Add(whenVote, vF) + } + } + return []simsx.SimAccount{proposer}, msg +} + +// TextProposalFactory returns a random text proposal content. +// A text proposal is a proposal that contains no msgs. +func TextProposalFactory() simsx.SimMsgFactoryFn[sdk.Msg] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, sdk.Msg) { + return nil, nil + } +} + +func randDeposit(ctx context.Context, proposal v1.Proposal, k *keeper.Keeper, r *simsx.XRand, reporter simsx.SimulationReporter) sdk.Coin { + params, err := k.Params.Get(ctx) + if err != nil { + reporter.Skipf("gov params: %s", err) + return sdk.Coin{} + } + minDeposits := params.MinDeposit + if proposal.ProposalType == v1.ProposalType_PROPOSAL_TYPE_EXPEDITED { + minDeposits = params.ExpeditedMinDeposit + } + minDeposit := simsx.OneOf(r, minDeposits) + minDepositRatio, err := sdkmath.LegacyNewDecFromStr(params.GetMinDepositRatio()) + if err != nil { + reporter.Skip(err.Error()) + return sdk.Coin{} + } + + threshold := minDeposit.Amount.ToLegacyDec().Mul(minDepositRatio).TruncateInt() + depositAmount, err := r.PositiveSDKIntInRange(threshold, minDeposit.Amount) + if err != nil { + reporter.Skipf("deposit amount: %s", err) + return sdk.Coin{} + } + return sdk.Coin{Denom: minDeposit.Denom, Amount: depositAmount} +} + +// Pick a random proposal ID between the initial proposal ID +// (defined in gov GenesisState) and the latest proposal ID +// that matches a given Status. +// It does not provide a default ID. +func randomProposalID(r *simsx.XRand, k *keeper.Keeper, ctx context.Context, status v1.ProposalStatus, s *SharedState) (proposalID uint64, found bool) { + proposalID, _ = k.ProposalID.Peek(ctx) + if initialProposalID := s.getMinProposalID(); initialProposalID == unsetProposalID { + s.setMinProposalID(proposalID) + } else if initialProposalID < proposalID { + proposalID = r.Uint64InRange(initialProposalID, proposalID) + } + proposal, err := k.Proposals.Get(ctx, proposalID) + if err != nil || proposal.Status != status { + return proposalID, false + } + + return proposalID, true +} + +// Pick a random weighted voting options +func randomWeightedVotingOptions(r *rand.Rand) v1.WeightedVoteOptions { + w1 := r.Intn(100 + 1) + w2 := r.Intn(100 - w1 + 1) + w3 := r.Intn(100 - w1 - w2 + 1) + w4 := 100 - w1 - w2 - w3 + weightedVoteOptions := v1.WeightedVoteOptions{} + if w1 > 0 { + weightedVoteOptions = append(weightedVoteOptions, &v1.WeightedVoteOption{ + Option: v1.OptionYes, + Weight: sdkmath.LegacyNewDecWithPrec(int64(w1), 2).String(), + }) + } + if w2 > 0 { + weightedVoteOptions = append(weightedVoteOptions, &v1.WeightedVoteOption{ + Option: v1.OptionAbstain, + Weight: sdkmath.LegacyNewDecWithPrec(int64(w2), 2).String(), + }) + } + if w3 > 0 { + weightedVoteOptions = append(weightedVoteOptions, &v1.WeightedVoteOption{ + Option: v1.OptionNo, + Weight: sdkmath.LegacyNewDecWithPrec(int64(w3), 2).String(), + }) + } + if w4 > 0 { + weightedVoteOptions = append(weightedVoteOptions, &v1.WeightedVoteOption{ + Option: v1.OptionNoWithVeto, + Weight: sdkmath.LegacyNewDecWithPrec(int64(w4), 2).String(), + }) + } + return weightedVoteOptions +} + +func randomVotingOption(r *rand.Rand) v1.VoteOption { + switch r.Intn(4) { + case 0: + return v1.OptionYes + case 1: + return v1.OptionAbstain + case 2: + return v1.OptionNo + case 3: + return v1.OptionNoWithVeto + default: + panic("invalid vote option") + } +} + +func must[T any](r T, err error) T { + if err != nil { + panic(err) + } + return r +} + +const unsetProposalID = 100000000000000 + +// SharedState shared state between message invocations +type SharedState struct { + minProposalID atomic.Uint64 +} + +// NewSharedState constructor +func NewSharedState() *SharedState { + r := &SharedState{} + r.setMinProposalID(unsetProposalID) + return r +} + +func (s *SharedState) getMinProposalID() uint64 { + return s.minProposalID.Load() +} + +func (s *SharedState) setMinProposalID(id uint64) { + s.minProposalID.Store(id) +} diff --git a/x/gov/simulation/operations.go b/x/gov/simulation/operations.go deleted file mode 100644 index a2749acb8cb3..000000000000 --- a/x/gov/simulation/operations.go +++ /dev/null @@ -1,752 +0,0 @@ -package simulation - -import ( - "math" - "math/rand" - "sync/atomic" - "time" - - sdkmath "cosmossdk.io/math" - "cosmossdk.io/x/gov/keeper" - "cosmossdk.io/x/gov/types" - v1 "cosmossdk.io/x/gov/types/v1" - - "github.com/cosmos/cosmos-sdk/client" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -const unsetProposalID = 100000000000000 - -// Governance message types and routes -var ( - TypeMsgDeposit = sdk.MsgTypeURL(&v1.MsgDeposit{}) - TypeMsgVote = sdk.MsgTypeURL(&v1.MsgVote{}) - TypeMsgVoteWeighted = sdk.MsgTypeURL(&v1.MsgVoteWeighted{}) - TypeMsgSubmitProposal = sdk.MsgTypeURL(&v1.MsgSubmitProposal{}) - TypeMsgCancelProposal = sdk.MsgTypeURL(&v1.MsgCancelProposal{}) -) - -// Simulation operation weights constants -const ( - OpWeightMsgDeposit = "op_weight_msg_deposit" - OpWeightMsgVote = "op_weight_msg_vote" - OpWeightMsgVoteWeighted = "op_weight_msg_weighted_vote" - OpWeightMsgCancelProposal = "op_weight_msg_cancel_proposal" - - DefaultWeightMsgDeposit = 100 - DefaultWeightMsgVote = 67 - DefaultWeightMsgVoteWeighted = 33 - DefaultWeightTextProposal = 5 - DefaultWeightMsgCancelProposal = 5 -) - -// SharedState shared state between message invocations -type SharedState struct { - minProposalID atomic.Uint64 -} - -// NewSharedState constructor -func NewSharedState() *SharedState { - r := &SharedState{} - r.setMinProposalID(unsetProposalID) - return r -} - -func (s *SharedState) getMinProposalID() uint64 { - return s.minProposalID.Load() -} - -func (s *SharedState) setMinProposalID(id uint64) { - s.minProposalID.Store(id) -} - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - appParams simtypes.AppParams, - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - wMsgs []simtypes.WeightedProposalMsg, - wContents []simtypes.WeightedProposalContent, //nolint:staticcheck // used for legacy testing -) simulation.WeightedOperations { - var ( - weightMsgDeposit int - weightMsgVote int - weightMsgVoteWeighted int - weightMsgCancelProposal int - ) - - appParams.GetOrGenerate(OpWeightMsgDeposit, &weightMsgDeposit, nil, - func(_ *rand.Rand) { - weightMsgDeposit = DefaultWeightMsgDeposit - }, - ) - - appParams.GetOrGenerate(OpWeightMsgVote, &weightMsgVote, nil, - func(_ *rand.Rand) { - weightMsgVote = DefaultWeightMsgVote - }, - ) - - appParams.GetOrGenerate(OpWeightMsgVoteWeighted, &weightMsgVoteWeighted, nil, - func(_ *rand.Rand) { - weightMsgVoteWeighted = DefaultWeightMsgVoteWeighted - }, - ) - - appParams.GetOrGenerate(OpWeightMsgCancelProposal, &weightMsgCancelProposal, nil, - func(_ *rand.Rand) { - weightMsgCancelProposal = DefaultWeightMsgCancelProposal - }, - ) - - // generate the weighted operations for the proposal msgs - var wProposalOps simulation.WeightedOperations - for _, wMsg := range wMsgs { - wMsg := wMsg // pin variable - var weight int - appParams.GetOrGenerate(wMsg.AppParamsKey(), &weight, nil, - func(_ *rand.Rand) { weight = wMsg.DefaultWeight() }, - ) - - wProposalOps = append( - wProposalOps, - simulation.NewWeightedOperation( - weight, - SimulateMsgSubmitProposal(txGen, ak, bk, k, wMsg.MsgSimulatorFn()), - ), - ) - } - - // generate the weighted operations for the proposal contents - var wLegacyProposalOps simulation.WeightedOperations - for _, wContent := range wContents { - wContent := wContent // pin variable - var weight int - appParams.GetOrGenerate(wContent.AppParamsKey(), &weight, nil, - func(_ *rand.Rand) { weight = wContent.DefaultWeight() }, - ) - - wLegacyProposalOps = append( - wLegacyProposalOps, - simulation.NewWeightedOperation( - weight, - SimulateMsgSubmitLegacyProposal(txGen, ak, bk, k, wContent.ContentSimulatorFn()), - ), - ) - } - state := NewSharedState() - wGovOps := simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgDeposit, - SimulateMsgDeposit(txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgVote, - SimulateMsgVote(txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgVoteWeighted, - SimulateMsgVoteWeighted(txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgCancelProposal, - SimulateMsgCancelProposal(txGen, ak, bk, k), - ), - } - - return append(wGovOps, append(wProposalOps, wLegacyProposalOps...)...) -} - -// SimulateMsgSubmitProposal simulates creating a msg Submit Proposal -// voting on the proposal, and subsequently slashing the proposal. It is implemented using -// future operations. -func SimulateMsgSubmitProposal( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - msgSim simtypes.MsgSimulatorFnX, -) simtypes.Operation { - return func(r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgs := []sdk.Msg{} - proposalMsg, err := msgSim(ctx, r, accs, ak.AddressCodec()) - if err != nil { - return simtypes.OperationMsg{}, nil, err - } - if proposalMsg != nil { - msgs = append(msgs, proposalMsg) - } - - return simulateMsgSubmitProposal(txGen, ak, bk, k, msgs)(r, app, ctx, accs, chainID) - } -} - -// SimulateMsgSubmitLegacyProposal simulates creating a msg Submit Proposal -// voting on the proposal, and subsequently slashing the proposal. It is implemented using -// future operations. -func SimulateMsgSubmitLegacyProposal( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - contentSim simtypes.ContentSimulatorFn, //nolint:staticcheck // used for legacy testing -) simtypes.Operation { - return func(r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - // 1) submit proposal now - content := contentSim(r, ctx, accs) - if content == nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgSubmitProposal, "content is nil"), nil, nil - } - - govacc, err := ak.AddressCodec().BytesToString(k.GetGovernanceAccount(ctx).GetAddress()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgSubmitProposal, "error getting governance account address"), nil, err - } - contentMsg, err := v1.NewLegacyContent(content, govacc) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgSubmitProposal, "error converting legacy content into proposal message"), nil, err - } - - return simulateMsgSubmitProposal(txGen, ak, bk, k, []sdk.Msg{contentMsg})(r, app, ctx, accs, chainID) - } -} - -func simulateMsgSubmitProposal( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - proposalMsgs []sdk.Msg, -) simtypes.Operation { - // The states are: - // column 1: All validators vote - // column 2: 90% vote - // column 3: 75% vote - // column 4: 40% vote - // column 5: 15% vote - // column 6: no one votes - // All columns sum to 100 for simplicity, values chosen by @valardragon semi-arbitrarily, - // feel free to change. - numVotesTransitionMatrix, _ := simulation.CreateTransitionMatrix([][]int{ - {20, 10, 0, 0, 0, 0}, - {55, 50, 20, 10, 0, 0}, - {25, 25, 30, 25, 30, 15}, - {0, 15, 30, 25, 30, 30}, - {0, 0, 20, 30, 30, 30}, - {0, 0, 0, 10, 10, 25}, - }) - - statePercentageArray := []float64{1, .9, .75, .4, .15, 0} - curNumVotesState := 1 - - return func( - r *rand.Rand, - app simtypes.AppEntrypoint, - ctx sdk.Context, - accs []simtypes.Account, - chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - simAccount, _ := simtypes.RandomAcc(r, accs) - expedited := r.Intn(2) == 0 - deposit, skip, err := randomDeposit(r, ctx, ak, bk, k, simAccount.Address, true, expedited) - switch { - case skip: - return simtypes.NoOpMsg(types.ModuleName, TypeMsgSubmitProposal, "skip deposit"), nil, nil - case err != nil: - return simtypes.NoOpMsg(types.ModuleName, TypeMsgSubmitProposal, "unable to generate deposit"), nil, err - } - - proposalType := v1.ProposalType_PROPOSAL_TYPE_STANDARD - if expedited { - proposalType = v1.ProposalType_PROPOSAL_TYPE_EXPEDITED - } - - accAddr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgSubmitProposal, "error getting simAccount address"), nil, err - } - msg, err := v1.NewMsgSubmitProposal( - proposalMsgs, - deposit, - accAddr, - simtypes.RandStringOfLength(r, 100), - simtypes.RandStringOfLength(r, 100), - simtypes.RandStringOfLength(r, 100), - proposalType, - ) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to generate a submit proposal msg"), nil, err - } - - account := ak.GetAccount(ctx, simAccount.Address) - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)}, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - simAccount.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - opMsg := simtypes.NewOperationMsg(msg, true, "") - - // get the submitted proposal ID - proposalID, err := k.ProposalID.Peek(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to generate proposalID"), nil, err - } - - // 2) Schedule operations for votes - // 2.1) first pick a number of people to vote. - curNumVotesState = numVotesTransitionMatrix.NextState(r, curNumVotesState) - numVotes := int(math.Ceil(float64(len(accs)) * statePercentageArray[curNumVotesState])) - - // 2.2) select who votes and when - whoVotes := r.Perm(len(accs)) - - // didntVote := whoVotes[numVotes:] - whoVotes = whoVotes[:numVotes] - params, _ := k.Params.Get(ctx) - votingPeriod := params.VotingPeriod - var fops []simtypes.FutureOperation - if false { // future ops deactivated because they were not implemented correct in the framework before and flood the system now - fops = make([]simtypes.FutureOperation, numVotes+1) - for i := 0; i < numVotes; i++ { - whenVote := ctx.HeaderInfo().Time.Add(time.Duration(r.Int63n(int64(votingPeriod.Seconds()))) * time.Second) - fops[i] = simtypes.FutureOperation{ - BlockTime: whenVote, - Op: func(r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accounts []simtypes.Account, chainID string) (OperationMsg simtypes.OperationMsg, futureOps []simtypes.FutureOperation, err error) { - return operationSimulateMsgVote(txGen, ak, bk, k, accs[whoVotes[i]], int64(proposalID), nil)(r, app, ctx, accounts, chainID) - }, - } - } - } - return opMsg, fops, nil - } -} - -// SimulateMsgDeposit generates a MsgDeposit with random values. -func SimulateMsgDeposit( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - simAccount, _ := simtypes.RandomAcc(r, accs) - proposalID, ok := randomProposalID(r, k, ctx, v1.StatusDepositPeriod, s) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgDeposit, "unable to generate proposalID"), nil, nil - } - - p, err := k.Proposals.Get(ctx, proposalID) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgDeposit, "unable to get proposal"), nil, err - } - - isExpedited := p.ProposalType == v1.ProposalType_PROPOSAL_TYPE_EXPEDITED - - deposit, skip, err := randomDeposit(r, ctx, ak, bk, k, simAccount.Address, false, isExpedited) - switch { - case skip: - return simtypes.NoOpMsg(types.ModuleName, TypeMsgDeposit, "skip deposit"), nil, nil - case err != nil: - return simtypes.NoOpMsg(types.ModuleName, TypeMsgDeposit, "unable to generate deposit"), nil, err - } - - addr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgDeposit, "unable to get simAccount address"), nil, err - } - msg := v1.NewMsgDeposit(addr, proposalID, deposit) - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - var fees sdk.Coins - coins, hasNeg := spendable.SafeSub(deposit...) - if !hasNeg { - fees, err = simtypes.RandomFees(r, coins) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to generate fees"), nil, err - } - } - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - ModuleName: types.ModuleName, - } - - return simulation.GenAndDeliverTx(txCtx, fees) - } -} - -// SimulateMsgVote generates a MsgVote with random values. -func SimulateMsgVote( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return operationSimulateMsgVote(txGen, ak, bk, k, simtypes.Account{}, -1, s) -} - -func operationSimulateMsgVote( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - simAccount simtypes.Account, - proposalIDInt int64, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - if simAccount.Equals(simtypes.Account{}) { - simAccount, _ = simtypes.RandomAcc(r, accs) - } - - var proposalID uint64 - - switch { - case proposalIDInt < 0: - var ok bool - proposalID, ok = randomProposalID(r, k, ctx, v1.StatusVotingPeriod, s) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgVote, "unable to generate proposalID"), nil, nil - } - default: - proposalID = uint64(proposalIDInt) - } - - option := randomVotingOption(r) - addr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgVote, "unable to get simAccount address"), nil, err - } - msg := v1.NewMsgVote(addr, proposalID, option, "") - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// SimulateMsgVoteWeighted generates a MsgVoteWeighted with random values. -func SimulateMsgVoteWeighted( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return operationSimulateMsgVoteWeighted(txGen, ak, bk, k, simtypes.Account{}, -1, s) -} - -func operationSimulateMsgVoteWeighted( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - simAccount simtypes.Account, - proposalIDInt int64, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - if simAccount.Equals(simtypes.Account{}) { - simAccount, _ = simtypes.RandomAcc(r, accs) - } - - var proposalID uint64 - - switch { - case proposalIDInt < 0: - var ok bool - proposalID, ok = randomProposalID(r, k, ctx, v1.StatusVotingPeriod, s) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgVoteWeighted, "unable to generate proposalID"), nil, nil - } - default: - proposalID = uint64(proposalIDInt) - } - - options := randomWeightedVotingOptions(r) - addr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgVoteWeighted, "unable to get simAccount address"), nil, err - } - msg := v1.NewMsgVoteWeighted(addr, proposalID, options, "") - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// SimulateMsgCancelProposal generates a MsgCancelProposal. -func SimulateMsgCancelProposal(txGen client.TxConfig, ak types.AccountKeeper, bk types.BankKeeper, k *keeper.Keeper) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - simAccount := accs[0] - proposal := randomProposal(r, k, ctx) - if proposal == nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgCancelProposal, "no proposals found"), nil, nil - } - - proposerAddr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgCancelProposal, "invalid proposer"), nil, err - } - if proposal.Proposer != proposerAddr { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgCancelProposal, "invalid proposer"), nil, nil - } - - if (proposal.Status != v1.StatusDepositPeriod) && (proposal.Status != v1.StatusVotingPeriod) { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgCancelProposal, "invalid proposal status"), nil, nil - } - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - accAddr, err := ak.AddressCodec().BytesToString(account.GetAddress()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgCancelProposal, "could not get account address"), nil, err - } - msg := v1.NewMsgCancelProposal(proposal.Id, accAddr) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// Pick a random deposit with a random denomination with a -// deposit amount between (0, min(balance, minDepositAmount)) -// This is to simulate multiple users depositing to get the -// proposal above the minimum deposit amount -func randomDeposit( - r *rand.Rand, - ctx sdk.Context, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - addr sdk.AccAddress, - useMinAmount bool, - expedited bool, -) (deposit sdk.Coins, skip bool, err error) { - account := ak.GetAccount(ctx, addr) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - if spendable.Empty() { - return nil, true, nil // skip - } - - params, _ := k.Params.Get(ctx) - minDeposit := params.MinDeposit - if expedited { - minDeposit = params.ExpeditedMinDeposit - } - denomIndex := r.Intn(len(minDeposit)) - denom := minDeposit[denomIndex].Denom - - spendableBalance := spendable.AmountOf(denom) - if spendableBalance.IsZero() { - return nil, true, nil - } - - minDepositAmount := minDeposit[denomIndex].Amount - - minDepositRatio, err := sdkmath.LegacyNewDecFromStr(params.GetMinDepositRatio()) - if err != nil { - return nil, false, err - } - - threshold := minDepositAmount.ToLegacyDec().Mul(minDepositRatio).TruncateInt() - - minAmount := sdkmath.ZeroInt() - if useMinAmount { - minDepositPercent, err := sdkmath.LegacyNewDecFromStr(params.MinInitialDepositRatio) - if err != nil { - return nil, false, err - } - - minAmount = sdkmath.LegacyNewDecFromInt(minDepositAmount).Mul(minDepositPercent).TruncateInt() - } - - amount, err := simtypes.RandPositiveInt(r, minDepositAmount.Sub(minAmount)) - if err != nil { - return nil, false, err - } - amount = amount.Add(minAmount) - - if amount.GT(spendableBalance) || amount.LT(threshold) { - return nil, true, nil - } - - return sdk.Coins{sdk.NewCoin(denom, amount)}, false, nil -} - -// randomProposal returns a random proposal stored in state -func randomProposal(r *rand.Rand, k *keeper.Keeper, ctx sdk.Context) *v1.Proposal { - var proposals []*v1.Proposal - err := k.Proposals.Walk(ctx, nil, func(key uint64, value v1.Proposal) (stop bool, err error) { - proposals = append(proposals, &value) - return false, nil - }) - if err != nil { - panic(err) - } - if len(proposals) == 0 { - return nil - } - randomIndex := r.Intn(len(proposals)) - return proposals[randomIndex] -} - -// Pick a random proposal ID between the initial proposal ID -// (defined in gov GenesisState) and the latest proposal ID -// that matches a given Status. -// It does not provide a default ID. -func randomProposalID(r *rand.Rand, k *keeper.Keeper, ctx sdk.Context, status v1.ProposalStatus, s *SharedState) (proposalID uint64, found bool) { - proposalID, _ = k.ProposalID.Peek(ctx) - if initialProposalID := s.getMinProposalID(); initialProposalID == unsetProposalID { - s.setMinProposalID(proposalID) - } else if initialProposalID < proposalID { - proposalID = uint64(simtypes.RandIntBetween(r, int(initialProposalID), int(proposalID))) - } - proposal, err := k.Proposals.Get(ctx, proposalID) - if err != nil || proposal.Status != status { - return proposalID, false - } - - return proposalID, true -} - -// Pick a random voting option -func randomVotingOption(r *rand.Rand) v1.VoteOption { - switch r.Intn(4) { - case 0: - return v1.OptionYes - case 1: - return v1.OptionAbstain - case 2: - return v1.OptionNo - case 3: - return v1.OptionNoWithVeto - default: - panic("invalid vote option") - } -} - -// Pick a random weighted voting options -func randomWeightedVotingOptions(r *rand.Rand) v1.WeightedVoteOptions { - w1 := r.Intn(100 + 1) - w2 := r.Intn(100 - w1 + 1) - w3 := r.Intn(100 - w1 - w2 + 1) - w4 := 100 - w1 - w2 - w3 - weightedVoteOptions := v1.WeightedVoteOptions{} - if w1 > 0 { - weightedVoteOptions = append(weightedVoteOptions, &v1.WeightedVoteOption{ - Option: v1.OptionYes, - Weight: sdkmath.LegacyNewDecWithPrec(int64(w1), 2).String(), - }) - } - if w2 > 0 { - weightedVoteOptions = append(weightedVoteOptions, &v1.WeightedVoteOption{ - Option: v1.OptionAbstain, - Weight: sdkmath.LegacyNewDecWithPrec(int64(w2), 2).String(), - }) - } - if w3 > 0 { - weightedVoteOptions = append(weightedVoteOptions, &v1.WeightedVoteOption{ - Option: v1.OptionNo, - Weight: sdkmath.LegacyNewDecWithPrec(int64(w3), 2).String(), - }) - } - if w4 > 0 { - weightedVoteOptions = append(weightedVoteOptions, &v1.WeightedVoteOption{ - Option: v1.OptionNoWithVeto, - Weight: sdkmath.LegacyNewDecWithPrec(int64(w4), 2).String(), - }) - } - return weightedVoteOptions -} diff --git a/x/gov/simulation/proposals.go b/x/gov/simulation/proposals.go index c53d024b13a5..471b51d6ebec 100644 --- a/x/gov/simulation/proposals.go +++ b/x/gov/simulation/proposals.go @@ -4,51 +4,15 @@ import ( "context" "math/rand" - coreaddress "cosmossdk.io/core/address" "cosmossdk.io/x/gov/types/v1beta1" - sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" ) -// OpWeightSubmitTextProposal app params key for text proposal -const OpWeightSubmitTextProposal = "op_weight_submit_text_proposal" - -// ProposalMsgs defines the module weighted proposals' contents -func ProposalMsgs() []simtypes.WeightedProposalMsg { - return []simtypes.WeightedProposalMsg{ - simulation.NewWeightedProposalMsgX( - OpWeightSubmitTextProposal, - DefaultWeightTextProposal, - SimulateTextProposal, - ), - } -} - -// SimulateTextProposal returns a random text proposal content. -// A text proposal is a proposal that contains no msgs. -func SimulateTextProposal(_ context.Context, r *rand.Rand, _ []simtypes.Account, _ coreaddress.Codec) (sdk.Msg, error) { - return nil, nil -} - -// ProposalContents defines the module weighted proposals' contents -// -//nolint:staticcheck // used for legacy testing -func ProposalContents() []simtypes.WeightedProposalContent { - return []simtypes.WeightedProposalContent{ - simulation.NewWeightedProposalContent( - OpWeightMsgDeposit, - DefaultWeightTextProposal, - SimulateLegacyTextProposalContent, - ), - } -} - -// SimulateTextProposalContent returns a random text proposal content. +// SimulateLegacyTextProposalContent returns a random text proposal content. // //nolint:staticcheck // used for legacy testing -func SimulateLegacyTextProposalContent(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) simtypes.Content { +func SimulateLegacyTextProposalContent(r *rand.Rand, _ context.Context, _ []simtypes.Account) simtypes.Content { return v1beta1.NewTextProposal( simtypes.RandStringOfLength(r, 140), simtypes.RandStringOfLength(r, 5000), diff --git a/x/gov/simulation/proposals_test.go b/x/gov/simulation/proposals_test.go deleted file mode 100644 index 939103c75ea9..000000000000 --- a/x/gov/simulation/proposals_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package simulation_test - -import ( - "context" - "math/rand" - "testing" - - "gotest.tools/v3/assert" - - "cosmossdk.io/x/gov/simulation" - - codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" -) - -func TestProposalMsgs(t *testing.T) { - // initialize parameters - s := rand.NewSource(1) - r := rand.New(s) - - accounts := simtypes.RandomAccounts(r, 3) - - // execute ProposalMsgs function - weightedProposalMsgs := simulation.ProposalMsgs() - assert.Assert(t, len(weightedProposalMsgs) == 1) - - w0 := weightedProposalMsgs[0] - - // tests w0 interface: - assert.Equal(t, simulation.OpWeightSubmitTextProposal, w0.AppParamsKey()) - assert.Equal(t, simulation.DefaultWeightTextProposal, w0.DefaultWeight()) - - msg, err := w0.MsgSimulatorFn()(context.Background(), r, accounts, codectestutil.CodecOptions{}.GetAddressCodec()) - assert.NilError(t, err) - assert.Assert(t, msg == nil) -} - -func TestProposalContents(t *testing.T) { - // initialize parameters - s := rand.NewSource(1) - r := rand.New(s) - - ctx := sdk.NewContext(nil, true, nil) - accounts := simtypes.RandomAccounts(r, 3) - - // execute ProposalContents function - weightedProposalContent := simulation.ProposalContents() - assert.Assert(t, len(weightedProposalContent) == 1) - - w0 := weightedProposalContent[0] - - // tests w0 interface: - assert.Equal(t, simulation.OpWeightMsgDeposit, w0.AppParamsKey()) - assert.Equal(t, simulation.DefaultWeightTextProposal, w0.DefaultWeight()) - - content := w0.ContentSimulatorFn()(r, ctx, accounts) - - assert.Equal(t, "NxImpptHBIFDQfnxaTiOBJUgNzvqHbVcVJYlIFWFlzFqqRTTyFzDUMntPzyRamUFqeJAEaSHIuUHZoTWDjWXsYxYvwXwXZEsjRQKgKMselyUqWXMbHzRNDHnMzhWSirUgVggjiBxtWDfhzPDgrorEoNmDEiDdBldYegphCBTYWrmFFXNjxhtygsGBFHTejaKjMsqNdikEzDalEyWRHfJhKqifCKsedVuuJbQMbmRVuIPDluAWGpngjgBjOxuRFwSadayHNIhVVmNWBbfaTOldclxTTLUMvaBnLfwjHTtsKetEIvgrxLijhKJNablmvqpWIWsmhWQAYNLycREypoASHnyKWrxpoNLBJuyCGysZJgXbQAAmSIbGxMFXuwMVGZgBiZWfPWorAfjBeekCFvljHAtVZaTOsRxbPIioNxLTnWUTzGTvaNhplQQPmMADRRDuUIsiBpnGqPheKmLnopieVseFdTSAvOCacxaqFWFuXzsrVZzlGfeRpClwKuGEBujaPrzSLjVIOMvLlWxuznEOXlxbZroBRVEvEfBBAHOECribZNrYiFnzQqQmBnLksmFNAadusWAGltuqYNntgOlgOGwSdDjWdLboWyAWIcCfmpGJTfbljKPriLehwObuszICkaXNUkmeddeeRulbZBXJVLgteiKIfofGdNBregwUPlINQECatDSNXSIuefyMxxoKfcmjHEwbVtFiXtEnLJkLHUghmzFiymrgBChucZgOQUpGGVQEpRtIQjIBxYhtZPgUORdxXNWUMErWrUeriqYJPcgIDgLMWAyuuQnsHncCtjvHmvFbzYErxeunQllYDUVlXaRBveRUKeXwEGJFTSAqZtaBSDGDtzlADCnGjuTmYMJlapRsWfugmjwKEuoXJVpZvlcHeFvVvRRktRVGwzLfKezPEMABZtbLExQIjynSoahmkmoTHefdzFoBHMcQHFkKVHhpNtudPqJrYuQswzFuFHbSmpNltFnYJpvMrAYHFrNouZaanEUGHvbHIUUFTCtZrcpRHwgjblxlDNJWzHdBNpAXKJPHWQdrGYcAHSctgVlqwqHoLfHsXUdStwfefwzqLuKEhmMyYLdbZrcPgYqjNHxPexsruwEGStAneKbWkQDDIlCWBLSiAASNhZqNFlPtfqPJoxKsgMdzjWqLWdqKQuJqWPMvwPQWZUtVMOTMYKJbfdlZsjdsomuScvDmbDkgRualsxDvRJuCAmPOXitIbcyWsKGSdrEunFAOdmXnsuyFVgJqEjbklvmwrUlsxjRSfKZxGcpayDdgoFcnVSutxjRgOSFzPwidAjubMncNweqpbxhXGchpZUxuFDOtpnhNUycJICRYqsPhPSCjPTWZFLkstHWJxvdPEAyEIxXgLwbNOjrgzmaujiBABBIXvcXpLrbcEWNNQsbjvgJFgJkflpRohHUutvnaUqoopuKjTDaemDeSdqbnOzcfJpcTuAQtZoiLZOoAIlboFDAeGmSNwkvObPRvRWQgWkGkxwtPauYgdkmypLjbqhlHJIQTntgWjXwZdOyYEdQRRLfMSdnxqppqUofqLbLQDUjwKVKfZJUJQPsWIPwIVaSTrmKskoAhvmZyJgeRpkaTfGgrJzAigcxtfshmiDCFkuiluqtMOkidknnTBtumyJYlIsWLnCQclqdVmikUoMOPdPWwYbJxXyqUVicNxFxyqJTenNblyyKSdlCbiXxUiYUiMwXZASYfvMDPFgxniSjWaZTjHkqlJvtBsXqwPpyVxnJVGFWhfSxgOcduoxkiopJvFjMmFabrGYeVtTXLhxVUEiGwYUvndjFGzDVntUvibiyZhfMQdMhgsiuysLMiePBNXifRLMsSmXPkwlPloUbJveCvUlaalhZHuvdkCnkSHbMbmOnrfEGPwQiACiPlnihiaOdbjPqPiTXaHDoJXjSlZmltGqNHHNrcKdlFSCdmVOuvDcBLdSklyGJmcLTbSFtALdGlPkqqecJrpLCXNPWefoTJNgEJlyMEPneVaxxduAAEqQpHWZodWyRkDAxzyMnFMcjSVqeRXLqsNyNtQBbuRvunZflWSbbvXXdkyLikYqutQhLPONXbvhcQZJPSWnOulqQaXmbfFxAkqfYeseSHOQidHwbcsOaMnSrrmGjjRmEMQNuknupMxJiIeVjmgZvbmjPIQTEhQFULQLBMPrxcFPvBinaOPYWGvYGRKxLZdwamfRQQFngcdSlvwjfaPbURasIsGJVHtcEAxnIIrhSriiXLOlbEBLXFElXJFGxHJczRBIxAuPKtBisjKBwfzZFagdNmjdwIRvwzLkFKWRTDPxJCmpzHUcrPiiXXHnOIlqNVoGSXZewdnCRhuxeYGPVTfrNTQNOxZmxInOazUYNTNDgzsxlgiVEHPKMfbesvPHUqpNkUqbzeuzfdrsuLDpKHMUbBMKczKKWOdYoIXoPYtEjfOnlQLoGnbQUCuERdEFaptwnsHzTJDsuZkKtzMpFaZobynZdzNydEeJJHDYaQcwUxcqvwfWwNUsCiLvkZQiSfzAHftYgAmVsXgtmcYgTqJIawstRYJrZdSxlfRiqTufgEQVambeZZmaAyRQbcmdjVUZZCgqDrSeltJGXPMgZnGDZqISrGDOClxXCxMjmKqEPwKHoOfOeyGmqWqihqjINXLqnyTesZePQRqaWDQNqpLgNrAUKulklmckTijUltQKuWQDwpLmDyxLppPVMwsmBIpOwQttYFMjgJQZLYFPmxWFLIeZihkRNnkzoypBICIxgEuYsVWGIGRbbxqVasYnstWomJnHwmtOhAFSpttRYYzBmyEtZXiCthvKvWszTXDbiJbGXMcrYpKAgvUVFtdKUfvdMfhAryctklUCEdjetjuGNfJjajZtvzdYaqInKtFPPLYmRaXPdQzxdSQfmZDEVHlHGEGNSPRFJuIfKLLfUmnHxHnRjmzQPNlqrXgifUdzAGKVabYqvcDeYoTYgPsBUqehrBhmQUgTvDnsdpuhUoxskDdppTsYMcnDIPSwKIqhXDCIxOuXrywahvVavvHkPuaenjLmEbMgrkrQLHEAwrhHkPRNvonNQKqprqOFVZKAtpRSpvQUxMoXCMZLSSbnLEFsjVfANdQNQVwTmGxqVjVqRuxREAhuaDrFgEZpYKhwWPEKBevBfsOIcaZKyykQafzmGPLRAKDtTcJxJVgiiuUkmyMYuDUNEUhBEdoBLJnamtLmMJQgmLiUELIhLpiEvpOXOvXCPUeldLFqkKOwfacqIaRcnnZvERKRMCKUkMABbDHytQqQblrvoxOZkwzosQfDKGtIdfcXRJNqlBNwOCWoQBcEWyqrMlYZIAXYJmLfnjoJepgSFvrgajaBAIksoyeHqgqbGvpAstMIGmIhRYGGNPRIfOQKsGoKgxtsidhTaAePRCBFqZgPDWCIkqOJezGVkjfYUCZTlInbxBXwUAVRsxHTQtJFnnpmMvXDYCVlEmnZBKhmmxQOIQzxFWpJQkQoSAYzTEiDWEOsVLNrbfzeHFRyeYATakQQWmFDLPbVMCJcWjFGJjfqCoVzlbNNEsqxdSmNPjTjHYOkuEMFLkXYGaoJlraLqayMeCsTjWNRDPBywBJLAPVkGQqTwApVVwYAetlwSbzsdHWsTwSIcctkyKDuRWYDQikRqsKTMJchrliONJeaZIzwPQrNbTwxsGdwuduvibtYndRwpdsvyCktRHFalvUuEKMqXbItfGcNGWsGzubdPMYayOUOINjpcFBeESdwpdlTYmrPsLsVDhpTzoMegKrytNVZkfJRPuDCUXxSlSthOohmsuxmIZUedzxKmowKOdXTMcEtdpHaPWgIsIjrViKrQOCONlSuazmLuCUjLltOGXeNgJKedTVrrVCpWYWHyVrdXpKgNaMJVjbXxnVMSChdWKuZdqpisvrkBJPoURDYxWOtpjzZoOpWzyUuYNhCzRoHsMjmmWDcXzQiHIyjwdhPNwiPqFxeUfMVFQGImhykFgMIlQEoZCaRoqSBXTSWAeDumdbsOGtATwEdZlLfoBKiTvodQBGOEcuATWXfiinSjPmJKcWgQrTVYVrwlyMWhxqNbCMpIQNoSMGTiWfPTCezUjYcdWppnsYJihLQCqbNLRGgqrwHuIvsazapTpoPZIyZyeeSueJuTIhpHMEJfJpScshJubJGfkusuVBgfTWQoywSSliQQSfbvaHKiLnyjdSbpMkdBgXepoSsHnCQaYuHQqZsoEOmJCiuQUpJkmfyfbIShzlZpHFmLCsbknEAkKXKfRTRnuwdBeuOGgFbJLbDksHVapaRayWzwoYBEpmrlAxrUxYMUekKbpjPNfjUCjhbdMAnJmYQVZBQZkFVweHDAlaqJjRqoQPoOMLhyvYCzqEuQsAFoxWrzRnTVjStPadhsESlERnKhpEPsfDxNvxqcOyIulaCkmPdambLHvGhTZzysvqFauEgkFRItPfvisehFmoBhQqmkfbHVsgfHXDPJVyhwPllQpuYLRYvGodxKjkarnSNgsXoKEMlaSKxKdcVgvOkuLcfLFfdtXGTclqfPOfeoVLbqcjcXCUEBgAGplrkgsmIEhWRZLlGPGCwKWRaCKMkBHTAcypUrYjWwCLtOPVygMwMANGoQwFnCqFrUGMCRZUGJKTZIGPyldsifauoMnJPLTcDHmilcmahlqOELaAUYDBuzsVywnDQfwRLGIWozYaOAilMBcObErwgTDNGWnwQMUgFFSKtPDMEoEQCTKVREqrXZSGLqwTMcxHfWotDllNkIJPMbXzjDVjPOOjCFuIvTyhXKLyhUScOXvYthRXpPfKwMhptXaxIxgqBoUqzrWbaoLTVpQoottZyPFfNOoMioXHRuFwMRYUiKvcWPkrayyTLOCFJlAyslDameIuqVAuxErqFPEWIScKpBORIuZqoXlZuTvAjEdlEWDODFRregDTqGNoFBIHxvimmIZwLfFyKUfEWAnNBdtdzDmTPXtpHRGdIbuucfTjOygZsTxPjf", content.GetDescription()) - assert.Equal(t, "XhSUkMhPjMaxKlMIJMOXcnQfyzeOcbWwNbeHVIkPZBSpYuLyYggwexjxusrBqDOTtGTOWeLrQKjLxzIivHSlcxgdXhhuTSkuxKGLwQvuyNhYFmBZHeAerqyNEUzXPFGkqEGqiQWIXnku", content.GetTitle()) - assert.Equal(t, "gov", content.ProposalRoute()) - assert.Equal(t, "Text", content.ProposalType()) -} diff --git a/x/gov/types/v1/genesis_test.go b/x/gov/types/v1/genesis_test.go index 7040446b06b7..fc26ecd9e2fc 100644 --- a/x/gov/types/v1/genesis_test.go +++ b/x/gov/types/v1/genesis_test.go @@ -175,7 +175,6 @@ func TestValidateGenesis(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := v1.ValidateGenesis(codec, tc.genesisState()) if tc.expErrMsg != "" { diff --git a/x/group/client/cli/tx_test.go b/x/group/client/cli/tx_test.go index 3707e0f310d1..2ad9ad76479c 100644 --- a/x/group/client/cli/tx_test.go +++ b/x/group/client/cli/tx_test.go @@ -220,8 +220,6 @@ func (s *CLITestSuite) TestTxCreateGroup() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { ctx := svrcmd.CreateExecuteContext(context.Background()) cmd.SetContext(ctx) @@ -336,8 +334,6 @@ func (s *CLITestSuite) TestTxUpdateGroupMembers() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { ctx := svrcmd.CreateExecuteContext(context.Background()) @@ -460,8 +456,6 @@ func (s *CLITestSuite) TestTxCreateGroupWithPolicy() { }, } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { ctx := svrcmd.CreateExecuteContext(context.Background()) @@ -597,8 +591,6 @@ func (s *CLITestSuite) TestTxCreateGroupPolicy() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { ctx := svrcmd.CreateExecuteContext(context.Background()) @@ -704,8 +696,6 @@ func (s *CLITestSuite) TestTxUpdateGroupPolicyDecisionPolicy() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { ctx := svrcmd.CreateExecuteContext(context.Background()) @@ -808,8 +798,6 @@ func (s *CLITestSuite) TestTxSubmitProposal() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { ctx := svrcmd.CreateExecuteContext(context.Background()) diff --git a/x/group/genesis_test.go b/x/group/genesis_test.go index 1671908fd63f..59753996d0bc 100644 --- a/x/group/genesis_test.go +++ b/x/group/genesis_test.go @@ -743,7 +743,6 @@ func TestGenesisStateValidate(t *testing.T) { }, } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := tc.genesisState.Validate() if tc.expErr { diff --git a/x/group/go.mod b/x/group/go.mod index 03719f7da3e7..e66922de057f 100644 --- a/x/group/go.mod +++ b/x/group/go.mod @@ -4,14 +4,14 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc - cosmossdk.io/x/accounts v0.0.0-20240226161501-23359a0b6d91 + cosmossdk.io/x/accounts v0.0.0-20240913065641-0064ccbce64e cosmossdk.io/x/authz v0.0.0-00010101000000-000000000000 cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 cosmossdk.io/x/consensus v0.0.0-00010101000000-000000000000 @@ -38,7 +38,8 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/collections v0.4.0 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect + cosmossdk.io/x/accounts/defaults/base v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 // indirect cosmossdk.io/x/accounts/defaults/multisig v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/distribution v0.0.0-00010101000000-000000000000 // indirect @@ -134,7 +135,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -188,6 +189,7 @@ replace ( cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/accounts => ../accounts + cosmossdk.io/x/accounts/defaults/base => ../accounts/defaults/base cosmossdk.io/x/accounts/defaults/lockup => ../accounts/defaults/lockup cosmossdk.io/x/accounts/defaults/multisig => ../accounts/defaults/multisig cosmossdk.io/x/authz => ../authz diff --git a/x/group/go.sum b/x/group/go.sum index 991c8e5d3928..1e6b3103221f 100644 --- a/x/group/go.sum +++ b/x/group/go.sum @@ -4,8 +4,8 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +14,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -410,8 +410,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/group/internal/orm/auto_uint64_test.go b/x/group/internal/orm/auto_uint64_test.go index c6e4870701c1..b61202f504e5 100644 --- a/x/group/internal/orm/auto_uint64_test.go +++ b/x/group/internal/orm/auto_uint64_test.go @@ -48,7 +48,6 @@ func TestAutoUInt64PrefixScan(t *testing.T) { Metadata: metadata, } for _, g := range []testdata.TableModel{t1, t2, t3} { - g := g _, err := tb.Create(store, &g) require.NoError(t, err) } diff --git a/x/group/internal/orm/index_test.go b/x/group/internal/orm/index_test.go index 24ae13b6d480..7e86fc4acba3 100644 --- a/x/group/internal/orm/index_test.go +++ b/x/group/internal/orm/index_test.go @@ -125,7 +125,6 @@ func TestIndexPrefixScan(t *testing.T) { Metadata: []byte("metadata-b"), } for _, g := range []testdata.TableModel{g1, g2, g3} { - g := g _, err := tb.Create(store, &g) require.NoError(t, err) } diff --git a/x/group/internal/orm/iterator.go b/x/group/internal/orm/iterator.go index c2612a4954fc..709a7f7a823c 100644 --- a/x/group/internal/orm/iterator.go +++ b/x/group/internal/orm/iterator.go @@ -298,7 +298,7 @@ func assertDest(dest ModelSlicePtr, destRef, tmpSlice *reflect.Value) (reflect.T protoMarshaler := reflect.TypeOf((*proto.Message)(nil)).Elem() if !elemType.Implements(protoMarshaler) && - !reflect.PtrTo(elemType).Implements(protoMarshaler) { + !reflect.PointerTo(elemType).Implements(protoMarshaler) { return nil, errorsmod.Wrapf(grouperrors.ErrORMInvalidArgument, "unsupported type :%s", elemType) } diff --git a/x/group/internal/orm/iterator_test.go b/x/group/internal/orm/iterator_test.go index bc3c29a57ea7..8ff344d61ea5 100644 --- a/x/group/internal/orm/iterator_test.go +++ b/x/group/internal/orm/iterator_test.go @@ -244,7 +244,6 @@ func TestPaginate(t *testing.T) { } for _, g := range []testdata.TableModel{t1, t2, t3, t4, t5} { - g := g _, err := tb.Create(store, &g) require.NoError(t, err) } diff --git a/x/group/internal/orm/orm_scenario_test.go b/x/group/internal/orm/orm_scenario_test.go index c666f4908116..f32037ccb7f0 100644 --- a/x/group/internal/orm/orm_scenario_test.go +++ b/x/group/internal/orm/orm_scenario_test.go @@ -281,7 +281,6 @@ func TestGasCostsPrimaryKeyTable(t *testing.T) { for i, m := range tms { testCtx.Ctx = testCtx.Ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()) - m := m err = k.primaryKeyTable.Delete(store, &m) require.NoError(t, err) diff --git a/x/group/internal/orm/primary_key_test.go b/x/group/internal/orm/primary_key_test.go index 7d0a77e36578..08cf2b71c560 100644 --- a/x/group/internal/orm/primary_key_test.go +++ b/x/group/internal/orm/primary_key_test.go @@ -48,7 +48,6 @@ func TestPrimaryKeyTablePrefixScan(t *testing.T) { Metadata: metadata, } for _, g := range []testdata.TableModel{t1, t2, t3} { - g := g require.NoError(t, tb.Create(store, &g)) } diff --git a/x/group/keeper/abci_test.go b/x/group/keeper/abci_test.go index 0db99839d51c..9cd40f8edb3d 100644 --- a/x/group/keeper/abci_test.go +++ b/x/group/keeper/abci_test.go @@ -332,7 +332,6 @@ func (s *IntegrationTestSuite) TestEndBlockerPruning() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { proposalID := spec.setupProposal(ctx) @@ -544,7 +543,6 @@ func (s *IntegrationTestSuite) TestEndBlockerTallying() { for msg, spec := range specs { s.Run(msg, func() { - spec := spec pID := spec.preRun(ctx) err := s.groupKeeper.EndBlocker(spec.newCtx) diff --git a/x/group/keeper/grpc_query_test.go b/x/group/keeper/grpc_query_test.go index 84f7a7c31a34..8f90ebd6e917 100644 --- a/x/group/keeper/grpc_query_test.go +++ b/x/group/keeper/grpc_query_test.go @@ -129,8 +129,6 @@ func TestQueryGroupInfo(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { _, err := fixture.queryClient.GroupInfo(fixture.ctx, &tc.req) if tc.expErrMsg != "" { @@ -169,7 +167,6 @@ func TestQueryGroupPolicyInfo(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { _, err := fixture.queryClient.GroupPolicyInfo(fixture.ctx, &tc.req) if tc.expErrMsg != "" { @@ -210,7 +207,6 @@ func TestQueryGroupMembers(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { resp, err := fixture.queryClient.GroupMembers(fixture.ctx, &tc.req) if tc.expErrMsg != "" { @@ -256,7 +252,6 @@ func TestQueryGroupsByAdmin(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { resp, err := fixture.queryClient.GroupsByAdmin(fixture.ctx, &tc.req) if tc.expErrMsg != "" { @@ -297,7 +292,6 @@ func TestQueryGroupPoliciesByGroup(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { resp, err := fixture.keeper.GroupPoliciesByGroup(fixture.ctx, &tc.req) if tc.expErrMsg != "" { @@ -343,7 +337,6 @@ func TestQueryGroupPoliciesByAdmin(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { resp, err := fixture.keeper.GroupPoliciesByAdmin(fixture.ctx, &tc.req) if tc.expErrMsg != "" { diff --git a/x/group/keeper/keeper.go b/x/group/keeper/keeper.go index b1fc76f920cc..5336704535dd 100644 --- a/x/group/keeper/keeper.go +++ b/x/group/keeper/keeper.go @@ -231,7 +231,7 @@ func NewKeeper(env appmodule.Environment, cdc codec.Codec, accKeeper group.Accou } // GetGroupSequence returns the current value of the group table sequence -func (k Keeper) GetGroupSequence(ctx sdk.Context) uint64 { +func (k Keeper) GetGroupSequence(ctx context.Context) uint64 { return k.groupTable.Sequence().CurVal(k.KVStoreService.OpenKVStore(ctx)) } @@ -379,8 +379,6 @@ func (k Keeper) PruneProposals(ctx context.Context) error { return nil } for _, proposal := range proposals { - proposal := proposal - err := k.pruneProposal(ctx, proposal.Id) if err != nil { return err diff --git a/x/group/keeper/keeper_test.go b/x/group/keeper/keeper_test.go index b07d1136280d..449fe039407f 100644 --- a/x/group/keeper/keeper_test.go +++ b/x/group/keeper/keeper_test.go @@ -115,7 +115,7 @@ func (s *TestSuite) SetupTest() { s.Require().NoError(err) s.setNextAccount() - groupSeq := s.groupKeeper.GetGroupSequence(s.sdkCtx) + groupSeq := s.groupKeeper.GetGroupSequence(s.ctx) s.Require().Equal(groupSeq, uint64(1)) policyRes, err := s.groupKeeper.CreateGroupPolicy(s.ctx, policyReq) @@ -273,7 +273,6 @@ func (s *TestSuite) TestProposalsByVPEnd() { } for msg, spec := range specs { - spec := spec s.Run(msg, func() { pID := spec.preRun(s.sdkCtx) diff --git a/x/group/keeper/msg_server.go b/x/group/keeper/msg_server.go index 79f449d3095f..5191b2dc3b4d 100644 --- a/x/group/keeper/msg_server.go +++ b/x/group/keeper/msg_server.go @@ -820,12 +820,11 @@ func (k Keeper) doTallyAndUpdate(ctx context.Context, p *group.Proposal, groupIn } // Exec executes the messages from a proposal. -func (k Keeper) Exec(goCtx context.Context, msg *group.MsgExec) (*group.MsgExecResponse, error) { +func (k Keeper) Exec(ctx context.Context, msg *group.MsgExec) (*group.MsgExecResponse, error) { if msg.ProposalId == 0 { return nil, errorsmod.Wrap(errors.ErrEmpty, "proposal id") } - ctx := sdk.UnwrapSDKContext(goCtx) proposal, err := k.getProposal(ctx, msg.ProposalId) if err != nil { return nil, err diff --git a/x/group/keeper/msg_server_test.go b/x/group/keeper/msg_server_test.go index a3e3f9274b43..d03f8721d563 100644 --- a/x/group/keeper/msg_server_test.go +++ b/x/group/keeper/msg_server_test.go @@ -169,7 +169,6 @@ func (s *TestSuite) TestCreateGroup() { var seq uint32 = 1 for msg, spec := range specs { - spec := spec s.Run(msg, func() { blockTime := sdk.UnwrapSDKContext(s.ctx).HeaderInfo().Time res, err := s.groupKeeper.CreateGroup(s.ctx, spec.req) @@ -520,7 +519,6 @@ func (s *TestSuite) TestUpdateGroupMembers() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { sdkCtx, _ := s.sdkCtx.CacheContext() _, err := s.groupKeeper.UpdateGroupMembers(sdkCtx, spec.req) @@ -657,7 +655,6 @@ func (s *TestSuite) TestUpdateGroupAdmin() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { _, err := s.groupKeeper.UpdateGroupAdmin(s.ctx, spec.req) if spec.expErr { @@ -727,7 +724,6 @@ func (s *TestSuite) TestUpdateGroupMetadata() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { sdkCtx, _ := s.sdkCtx.CacheContext() _, err := s.groupKeeper.UpdateGroupMetadata(sdkCtx, spec.req) @@ -897,7 +893,6 @@ func (s *TestSuite) TestCreateGroupWithPolicy() { } for msg, spec := range specs { - spec := spec s.Run(msg, func() { s.setNextAccount() err := spec.req.SetDecisionPolicy(spec.policy) @@ -1084,7 +1079,6 @@ func (s *TestSuite) TestCreateGroupPolicy() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { err := spec.req.SetDecisionPolicy(spec.policy) s.Require().NoError(err) @@ -1218,7 +1212,7 @@ func (s *TestSuite) TestUpdateGroupPolicyAdmin() { }, } for msg, spec := range specs { - spec := spec + err := spec.expGroupPolicy.SetDecisionPolicy(policy) s.Require().NoError(err) @@ -1369,7 +1363,7 @@ func (s *TestSuite) TestUpdateGroupPolicyDecisionPolicy() { }, } for msg, spec := range specs { - spec := spec + policyAddr := groupPolicyAddr err := spec.expGroupPolicy.SetDecisionPolicy(spec.policy) s.Require().NoError(err) @@ -1470,7 +1464,7 @@ func (s *TestSuite) TestUpdateGroupPolicyMetadata() { }, } for msg, spec := range specs { - spec := spec + err := spec.expGroupPolicy.SetDecisionPolicy(policy) s.Require().NoError(err) @@ -1877,7 +1871,6 @@ func (s *TestSuite) TestSubmitProposal() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { err := spec.req.SetMsgs(spec.msgs) s.Require().NoError(err) @@ -2002,7 +1995,7 @@ func (s *TestSuite) TestWithdrawProposal() { }, } for msg, spec := range specs { - spec := spec + s.Run(msg, func() { pID := spec.preRun(s.sdkCtx) @@ -2385,7 +2378,6 @@ func (s *TestSuite) TestVote() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { sdkCtx := s.sdkCtx if !spec.srcCtx.IsZero() { @@ -2738,7 +2730,6 @@ func (s *TestSuite) TestExecProposal() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { sdkCtx, _ := s.sdkCtx.CacheContext() proposalID := spec.setupProposal(sdkCtx) @@ -2782,7 +2773,6 @@ func (s *TestSuite) TestExecProposal() { } spec.postRun(sdkCtx) }) - } } @@ -2935,7 +2925,6 @@ func (s *TestSuite) TestExecPrunedProposalsAndVotes() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { sdkCtx, _ := s.sdkCtx.CacheContext() proposalID := spec.setupProposal(sdkCtx) @@ -3343,7 +3332,6 @@ func (s *TestSuite) TestExecProposalsWhenMemberLeavesOrIsUpdated() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { sdkCtx, _ := s.sdkCtx.CacheContext() @@ -3365,7 +3353,7 @@ func (s *TestSuite) TestExecProposalsWhenMemberLeavesOrIsUpdated() { s.setNextAccount() - s.groupKeeper.GetGroupSequence(s.sdkCtx) + s.groupKeeper.GetGroupSequence(s.ctx) policyRes, err := s.groupKeeper.CreateGroupPolicy(s.ctx, policyReq) s.Require().NoError(err) diff --git a/x/group/keeper/tally_test.go b/x/group/keeper/tally_test.go index 80528675144a..0b8575fa1610 100644 --- a/x/group/keeper/tally_test.go +++ b/x/group/keeper/tally_test.go @@ -66,7 +66,6 @@ func (s *TestSuite) TestTally() { } for msg, spec := range specs { - spec := spec s.Run(msg, func() { sdkCtx, _ := s.sdkCtx.CacheContext() pID := spec.setupProposal(sdkCtx) diff --git a/x/group/module/module.go b/x/group/module/module.go index 3f6aecffd827..97b0b40118b7 100644 --- a/x/group/module/module.go +++ b/x/group/module/module.go @@ -19,6 +19,7 @@ import ( sdkclient "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/simsx" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" @@ -160,11 +161,21 @@ func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[group.StoreKey] = simulation.NewDecodeStore(am.cdc) } -// WeightedOperations returns the all the gov module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - am.registry, - simState.AppParams, simState.Cdc, simState.TxConfig, - am.accKeeper, am.bankKeeper, am.keeper, am.cdc, - ) +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + s := simulation.NewSharedState() + // note: using old keys for backwards compatibility + reg.Add(weights.Get("msg_create_group", 100), simulation.MsgCreateGroupFactory()) + reg.Add(weights.Get("msg_update_group_admin", 5), simulation.MsgUpdateGroupAdminFactory(am.keeper, s)) + reg.Add(weights.Get("msg_update_group_metadata", 5), simulation.MsgUpdateGroupMetadataFactory(am.keeper, s)) + reg.Add(weights.Get("msg_update_group_members", 5), simulation.MsgUpdateGroupMembersFactory(am.keeper, s)) + reg.Add(weights.Get("msg_create_group_account", 50), simulation.MsgCreateGroupPolicyFactory(am.keeper, s)) + reg.Add(weights.Get("msg_create_group_with_policy", 50), simulation.MsgCreateGroupWithPolicyFactory()) + reg.Add(weights.Get("msg_update_group_account_admin", 5), simulation.MsgUpdateGroupPolicyAdminFactory(am.keeper, s)) + reg.Add(weights.Get("msg_update_group_account_decision_policy", 5), simulation.MsgUpdateGroupPolicyDecisionPolicyFactory(am.keeper, s)) + reg.Add(weights.Get("msg_update_group_account_metadata", 5), simulation.MsgUpdateGroupPolicyMetadataFactory(am.keeper, s)) + reg.Add(weights.Get("msg_submit_proposal", 2*90), simulation.MsgSubmitProposalFactory(am.keeper, s)) + reg.Add(weights.Get("msg_withdraw_proposal", 20), simulation.MsgWithdrawProposalFactory(am.keeper, s)) + reg.Add(weights.Get("msg_vote", 90), simulation.MsgVoteFactory(am.keeper, s)) + reg.Add(weights.Get("msg_exec", 90), simulation.MsgExecFactory(am.keeper, s)) + reg.Add(weights.Get("msg_leave_group", 5), simulation.MsgLeaveGroupFactory(am.keeper, s)) } diff --git a/x/group/simulation/decoder_test.go b/x/group/simulation/decoder_test.go index ee4a995907c9..2c6cd2d1d670 100644 --- a/x/group/simulation/decoder_test.go +++ b/x/group/simulation/decoder_test.go @@ -78,7 +78,6 @@ func TestDecodeStore(t *testing.T) { } for i, tt := range tests { - i, tt := i, tt t.Run(tt.name, func(t *testing.T) { if tt.expectErr { require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) diff --git a/x/group/simulation/genesis.go b/x/group/simulation/genesis.go index 2049e8a4ac15..f94fe0da18c1 100644 --- a/x/group/simulation/genesis.go +++ b/x/group/simulation/genesis.go @@ -4,7 +4,6 @@ import ( "math/rand" "time" - "cosmossdk.io/core/address" banktypes "cosmossdk.io/x/bank/types" "cosmossdk.io/x/group" @@ -31,14 +30,11 @@ func checkAccExists(acc string, g []*group.GroupMember, lastIndex int) bool { return false } -func getGroups(r *rand.Rand, accounts []simtypes.Account, addressCodec address.Codec) []*group.GroupInfo { +func getGroups(r *rand.Rand, accounts []simtypes.Account) []*group.GroupInfo { groups := make([]*group.GroupInfo, 3) for i := 0; i < 3; i++ { acc, _ := simtypes.RandomAcc(r, accounts) - accAddr, err := addressCodec.BytesToString(acc.Address) - if err != nil { - return nil - } + accAddr := acc.AddressBech32 groups[i] = &group.GroupInfo{ Id: uint64(i + 1), Admin: accAddr, @@ -50,20 +46,14 @@ func getGroups(r *rand.Rand, accounts []simtypes.Account, addressCodec address.C return groups } -func getGroupMembers(r *rand.Rand, accounts []simtypes.Account, addressCodec address.Codec) []*group.GroupMember { +func getGroupMembers(r *rand.Rand, accounts []simtypes.Account) []*group.GroupMember { groupMembers := make([]*group.GroupMember, 3) for i := 0; i < 3; i++ { acc, _ := simtypes.RandomAcc(r, accounts) - accAddr, err := addressCodec.BytesToString(acc.Address) - if err != nil { - return nil - } + accAddr := acc.AddressBech32 for checkAccExists(accAddr, groupMembers, i) { acc, _ = simtypes.RandomAcc(r, accounts) - accAddr, err = addressCodec.BytesToString(acc.Address) - if err != nil { - return nil - } + accAddr = acc.AddressBech32 } groupMembers[i] = &group.GroupMember{ GroupId: uint64(i + 1), @@ -83,11 +73,7 @@ func getGroupPolicies(r *rand.Rand, simState *module.SimulationState) []*group.G usedAccs := make(map[string]bool) for i := 0; i < 3; i++ { acc, _ := simtypes.RandomAcc(r, simState.Accounts) - accAddr, err := simState.AddressCodec.BytesToString(acc.Address) - if err != nil { - return nil - } - if usedAccs[accAddr] { + if usedAccs[acc.AddressBech32] { if len(usedAccs) != len(simState.Accounts) { // Go again if the account is used and there are more to take from i-- @@ -95,7 +81,7 @@ func getGroupPolicies(r *rand.Rand, simState *module.SimulationState) []*group.G continue } - usedAccs[accAddr] = true + usedAccs[acc.AddressBech32] = true any, err := codectypes.NewAnyWithValue(group.NewThresholdDecisionPolicy("10", time.Second, 0)) if err != nil { @@ -103,8 +89,8 @@ func getGroupPolicies(r *rand.Rand, simState *module.SimulationState) []*group.G } groupPolicies = append(groupPolicies, &group.GroupPolicyInfo{ GroupId: uint64(i + 1), - Admin: accAddr, - Address: accAddr, + Admin: acc.AddressBech32, + Address: acc.AddressBech32, Version: 1, DecisionPolicy: any, Metadata: simtypes.RandStringOfLength(r, 10), @@ -115,14 +101,8 @@ func getGroupPolicies(r *rand.Rand, simState *module.SimulationState) []*group.G func getProposals(r *rand.Rand, simState *module.SimulationState, groupPolicies []*group.GroupPolicyInfo) []*group.Proposal { proposals := make([]*group.Proposal, 3) - addr0, err := simState.AddressCodec.BytesToString(simState.Accounts[0].Address) - if err != nil { - panic(err) - } - addr1, err := simState.AddressCodec.BytesToString(simState.Accounts[1].Address) - if err != nil { - panic(err) - } + addr0 := simState.Accounts[0].AddressBech32 + addr1 := simState.Accounts[1].AddressBech32 proposers := []string{addr0, addr1} for i := 0; i < 3; i++ { idx := r.Intn(len(groupPolicies)) @@ -151,14 +131,9 @@ func getProposals(r *rand.Rand, simState *module.SimulationState, groupPolicies VotingPeriodEnd: timeout, } - toAddr, err := simState.AddressCodec.BytesToString(to.Address) - if err != nil { - panic(err) - } - - err = proposal.SetMsgs([]sdk.Msg{&banktypes.MsgSend{ + err := proposal.SetMsgs([]sdk.Msg{&banktypes.MsgSend{ FromAddress: groupPolicyAddress, - ToAddress: toAddr, + ToAddress: to.AddressBech32, Amount: sdk.NewCoins(sdk.NewInt64Coin("test", 10)), }}) if err != nil { @@ -175,10 +150,7 @@ func getVotes(r *rand.Rand, simState *module.SimulationState) []*group.Vote { votes := make([]*group.Vote, 3) for i := 0; i < 3; i++ { - voterAddr, err := simState.AddressCodec.BytesToString(simState.Accounts[i].Address) - if err != nil { - return nil - } + voterAddr := simState.Accounts[i].AddressBech32 votes[i] = &group.Vote{ ProposalId: uint64(i + 1), Voter: voterAddr, @@ -213,11 +185,11 @@ func RandomizedGenState(simState *module.SimulationState) { // groups var groups []*group.GroupInfo - simState.AppParams.GetOrGenerate(GroupInfo, &groups, simState.Rand, func(r *rand.Rand) { groups = getGroups(r, simState.Accounts, simState.AddressCodec) }) + simState.AppParams.GetOrGenerate(GroupInfo, &groups, simState.Rand, func(r *rand.Rand) { groups = getGroups(r, simState.Accounts) }) // group members var members []*group.GroupMember - simState.AppParams.GetOrGenerate(GroupMembers, &members, simState.Rand, func(r *rand.Rand) { members = getGroupMembers(r, simState.Accounts, simState.AddressCodec) }) + simState.AppParams.GetOrGenerate(GroupMembers, &members, simState.Rand, func(r *rand.Rand) { members = getGroupMembers(r, simState.Accounts) }) // group policies var groupPolicies []*group.GroupPolicyInfo diff --git a/x/group/simulation/msg_factory.go b/x/group/simulation/msg_factory.go new file mode 100644 index 000000000000..30b55fc498ce --- /dev/null +++ b/x/group/simulation/msg_factory.go @@ -0,0 +1,487 @@ +package simulation + +import ( + "context" + "slices" + "strconv" + "sync/atomic" + "time" + + "cosmossdk.io/x/group" + "cosmossdk.io/x/group/keeper" + + "github.com/cosmos/cosmos-sdk/simsx" +) + +const unsetGroupID = 100000000000000 + +// SharedState shared state between message invocations +type SharedState struct { + minGroupID atomic.Uint64 +} + +// NewSharedState constructor +func NewSharedState() *SharedState { + r := &SharedState{} + r.setMinGroupID(unsetGroupID) + return r +} + +func (s *SharedState) getMinGroupID() uint64 { + return s.minGroupID.Load() +} + +func (s *SharedState) setMinGroupID(id uint64) { + s.minGroupID.Store(id) +} + +func MsgCreateGroupFactory() simsx.SimMsgFactoryFn[*group.MsgCreateGroup] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgCreateGroup) { + admin := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + members := genGroupMembersX(testData, reporter) + msg := &group.MsgCreateGroup{Admin: admin.AddressBech32, Members: members, Metadata: testData.Rand().StringN(10)} + return []simsx.SimAccount{admin}, msg + } +} + +func MsgCreateGroupPolicyFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgCreateGroupPolicy] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgCreateGroupPolicy) { + groupInfo := randomGroupX(ctx, k, testData, reporter, s) + groupAdmin := testData.GetAccount(reporter, groupInfo.Admin) + if reporter.IsSkipped() { + return nil, nil + } + groupID := groupInfo.Id + + r := testData.Rand() + msg, err := group.NewMsgCreateGroupPolicy( + groupAdmin.AddressBech32, + groupID, + r.StringN(10), + &group.ThresholdDecisionPolicy{ + Threshold: strconv.Itoa(r.IntInRange(1, 10)), + Windows: &group.DecisionPolicyWindows{ + VotingPeriod: time.Second * time.Duration(30*24*60*60), + }, + }, + ) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + return []simsx.SimAccount{groupAdmin}, msg + } +} + +func MsgCreateGroupWithPolicyFactory() simsx.SimMsgFactoryFn[*group.MsgCreateGroupWithPolicy] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgCreateGroupWithPolicy) { + admin := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + members := genGroupMembersX(testData, reporter) + r := testData.Rand() + msg := &group.MsgCreateGroupWithPolicy{ + Admin: admin.AddressBech32, + Members: members, + GroupMetadata: r.StringN(10), + GroupPolicyMetadata: r.StringN(10), + GroupPolicyAsAdmin: r.Float32() < 0.5, + } + decisionPolicy := &group.ThresholdDecisionPolicy{ + Threshold: strconv.Itoa(r.IntInRange(1, 10)), + Windows: &group.DecisionPolicyWindows{ + VotingPeriod: time.Second * time.Duration(30*24*60*60), + }, + } + if err := msg.SetDecisionPolicy(decisionPolicy); err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + return []simsx.SimAccount{admin}, msg + } +} + +func MsgWithdrawProposalFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgWithdrawProposal] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgWithdrawProposal) { + groupInfo, groupPolicy := randomGroupPolicyX(ctx, testData, reporter, k, s) + if reporter.IsSkipped() { + return nil, nil + } + policy, err := groupPolicy.GetDecisionPolicy() + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + err = policy.Validate(*groupInfo, group.DefaultConfig()) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + proposalsResult, err := k.ProposalsByGroupPolicy(ctx, + &group.QueryProposalsByGroupPolicyRequest{Address: groupPolicy.Address}, + ) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + + now := simsx.BlockTime(ctx) + proposal := simsx.First(proposalsResult.GetProposals(), func(p *group.Proposal) bool { + return p.Status == group.PROPOSAL_STATUS_SUBMITTED && p.VotingPeriodEnd.After(now) + }) + if proposal == nil { + reporter.Skip("no proposal found") + return nil, nil + } + // select a random proposer + r := testData.Rand() + proposer := testData.GetAccount(reporter, simsx.OneOf(r, (*proposal).Proposers)) + + msg := &group.MsgWithdrawProposal{ + ProposalId: (*proposal).Id, + Address: proposer.AddressBech32, + } + return []simsx.SimAccount{proposer}, msg + } +} + +func MsgVoteFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgVote] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgVote) { + groupInfo, groupPolicy := randomGroupPolicyX(ctx, testData, reporter, k, s) + if reporter.IsSkipped() { + return nil, nil + } + proposalsResult, err := k.ProposalsByGroupPolicy(ctx, + &group.QueryProposalsByGroupPolicyRequest{Address: groupPolicy.Address}, + ) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + + now := simsx.BlockTime(ctx) + proposal := simsx.First(proposalsResult.GetProposals(), func(p *group.Proposal) bool { + return p.Status == group.PROPOSAL_STATUS_SUBMITTED && p.VotingPeriodEnd.After(now) + }) + if proposal == nil { + reporter.Skip("no proposal found") + return nil, nil + } + // select a random member + r := testData.Rand() + res, err := k.GroupMembers(ctx, &group.QueryGroupMembersRequest{GroupId: groupInfo.Id}) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + if len(res.Members) == 0 { + reporter.Skip("group has no members") + return nil, nil + } + voter := testData.GetAccount(reporter, simsx.OneOf(r, res.Members).Member.Address) + vRes, err := k.VotesByProposal(ctx, &group.QueryVotesByProposalRequest{ + ProposalId: (*proposal).Id, + }) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + if slices.ContainsFunc(vRes.Votes, func(v *group.Vote) bool { return v.Voter == voter.AddressBech32 }) { + reporter.Skip("voted already on proposal") + return nil, nil + } + + msg := &group.MsgVote{ + ProposalId: (*proposal).Id, + Voter: voter.AddressBech32, + Option: group.VOTE_OPTION_YES, + Metadata: r.StringN(10), + } + return []simsx.SimAccount{voter}, msg + } +} + +func MsgSubmitProposalFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgSubmitProposal] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgSubmitProposal) { + groupInfo, groupPolicy := randomGroupPolicyX(ctx, testData, reporter, k, s) + if reporter.IsSkipped() { + return nil, nil + } + // Return a no-op if we know the proposal cannot be created + policy, err := groupPolicy.GetDecisionPolicy() + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + + if err = policy.Validate(*groupInfo, group.DefaultConfig()); err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + + // Pick a random member from the group + r := testData.Rand() + res, err := k.GroupMembers(ctx, &group.QueryGroupMembersRequest{GroupId: groupInfo.Id}) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + if len(res.Members) == 0 { + reporter.Skip("group has no members") + return nil, nil + } + proposer := testData.GetAccount(reporter, simsx.OneOf(r, res.Members).Member.Address) + + msg := &group.MsgSubmitProposal{ + GroupPolicyAddress: groupPolicy.Address, + Proposers: []string{proposer.AddressBech32}, + Metadata: r.StringN(10), + Title: "Test Proposal", + Summary: "Summary of the proposal", + } + return []simsx.SimAccount{proposer}, msg + } +} + +func MsgExecFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgExec] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgExec) { + groupPolicy, policyAdmin := randomGroupPolicyWithAdmin(ctx, testData, reporter, k, s) + if reporter.IsSkipped() { + return nil, nil + } + proposalsResult, err := k.ProposalsByGroupPolicy(ctx, + &group.QueryProposalsByGroupPolicyRequest{Address: groupPolicy.Address}, + ) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + + proposal := simsx.First(proposalsResult.GetProposals(), func(p *group.Proposal) bool { + return p.Status == group.PROPOSAL_STATUS_ACCEPTED + }) + if proposal == nil { + reporter.Skip("no proposal found") + return nil, nil + } + + msg := &group.MsgExec{ + ProposalId: (*proposal).Id, + Executor: policyAdmin.AddressBech32, + } + return []simsx.SimAccount{policyAdmin}, msg + } +} + +func randomGroupPolicyWithAdmin(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter, k keeper.Keeper, s *SharedState) (*group.GroupPolicyInfo, simsx.SimAccount) { + for i := 0; i < 5; i++ { + _, groupPolicy := randomGroupPolicyX(ctx, testData, reporter, k, s) + if groupPolicy != nil && testData.HasAccount(groupPolicy.Admin) { + return groupPolicy, testData.GetAccount(reporter, groupPolicy.Admin) + } + } + reporter.Skip("no group policy found with a sims account") + return nil, simsx.SimAccount{} +} + +func MsgUpdateGroupMetadataFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgUpdateGroupMetadata] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgUpdateGroupMetadata) { + groupInfo := randomGroupX(ctx, k, testData, reporter, s) + groupAdmin := testData.GetAccount(reporter, groupInfo.Admin) + if reporter.IsSkipped() { + return nil, nil + } + msg := &group.MsgUpdateGroupMetadata{ + GroupId: groupInfo.Id, + Admin: groupAdmin.AddressBech32, + Metadata: testData.Rand().StringN(10), + } + return []simsx.SimAccount{groupAdmin}, msg + } +} + +func MsgUpdateGroupAdminFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgUpdateGroupAdmin] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgUpdateGroupAdmin) { + groupInfo := randomGroupX(ctx, k, testData, reporter, s) + groupAdmin := testData.GetAccount(reporter, groupInfo.Admin) + if reporter.IsSkipped() { + return nil, nil + } + newAdmin := testData.AnyAccount(reporter, simsx.ExcludeAccounts(groupAdmin)) + msg := &group.MsgUpdateGroupAdmin{ + GroupId: groupInfo.Id, + Admin: groupAdmin.AddressBech32, + NewAdmin: newAdmin.AddressBech32, + } + return []simsx.SimAccount{groupAdmin}, msg + } +} + +func MsgUpdateGroupMembersFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgUpdateGroupMembers] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgUpdateGroupMembers) { + groupInfo := randomGroupX(ctx, k, testData, reporter, s) + groupAdmin := testData.GetAccount(reporter, groupInfo.Admin) + if reporter.IsSkipped() { + return nil, nil + } + res, err := k.GroupMembers(ctx, &group.QueryGroupMembersRequest{GroupId: groupInfo.Id}) + if err != nil { + reporter.Skip("group members not found") + return nil, nil + } + oldMemberAddrs := simsx.Collect(res.Members, func(a *group.GroupMember) string { return a.Member.Address }) + members := genGroupMembersX(testData, reporter, simsx.ExcludeAddresses(oldMemberAddrs...)) + if len(res.Members) != 0 { + // set existing random group member weight to zero to remove from the group + obsoleteMember := simsx.OneOf(testData.Rand(), res.Members) + obsoleteMember.Member.Weight = "0" + members = append(members, group.MemberToMemberRequest(obsoleteMember.Member)) + } + msg := &group.MsgUpdateGroupMembers{ + GroupId: groupInfo.Id, + Admin: groupAdmin.AddressBech32, + MemberUpdates: members, + } + return []simsx.SimAccount{groupAdmin}, msg + } +} + +func MsgUpdateGroupPolicyAdminFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgUpdateGroupPolicyAdmin] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgUpdateGroupPolicyAdmin) { + groupPolicy, policyAdmin := randomGroupPolicyWithAdmin(ctx, testData, reporter, k, s) + if reporter.IsSkipped() { + return nil, nil + } + newAdmin := testData.AnyAccount(reporter, simsx.ExcludeAccounts(policyAdmin)) + msg := &group.MsgUpdateGroupPolicyAdmin{ + Admin: policyAdmin.AddressBech32, + GroupPolicyAddress: groupPolicy.Address, + NewAdmin: newAdmin.AddressBech32, + } + return []simsx.SimAccount{policyAdmin}, msg + } +} + +func MsgUpdateGroupPolicyDecisionPolicyFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgUpdateGroupPolicyDecisionPolicy] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgUpdateGroupPolicyDecisionPolicy) { + groupPolicy, policyAdmin := randomGroupPolicyWithAdmin(ctx, testData, reporter, k, s) + if reporter.IsSkipped() { + return nil, nil + } + r := testData.Rand() + msg, err := group.NewMsgUpdateGroupPolicyDecisionPolicy(policyAdmin.AddressBech32, groupPolicy.Address, &group.ThresholdDecisionPolicy{ + Threshold: strconv.Itoa(r.IntInRange(1, 10)), + Windows: &group.DecisionPolicyWindows{ + VotingPeriod: time.Second * time.Duration(r.IntInRange(100, 1000)), + }, + }) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + return []simsx.SimAccount{policyAdmin}, msg + } +} + +func MsgUpdateGroupPolicyMetadataFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgUpdateGroupPolicyMetadata] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgUpdateGroupPolicyMetadata) { + groupPolicy, policyAdmin := randomGroupPolicyWithAdmin(ctx, testData, reporter, k, s) + if reporter.IsSkipped() { + return nil, nil + } + msg := &group.MsgUpdateGroupPolicyMetadata{ + Admin: policyAdmin.AddressBech32, + GroupPolicyAddress: groupPolicy.Address, + Metadata: testData.Rand().StringN(10), + } + return []simsx.SimAccount{policyAdmin}, msg + } +} + +func MsgLeaveGroupFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgLeaveGroup] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgLeaveGroup) { + groupInfo := randomGroupX(ctx, k, testData, reporter, s) + if reporter.IsSkipped() { + return nil, nil + } + res, err := k.GroupMembers(ctx, &group.QueryGroupMembersRequest{GroupId: groupInfo.Id}) + if err != nil { + reporter.Skip("group members not found") + return nil, nil + } + if len(res.Members) == 0 { + reporter.Skip("group has no members") + return nil, nil + } + anyMember := simsx.OneOf(testData.Rand(), res.Members) + leaver := testData.GetAccount(reporter, anyMember.Member.Address) + msg := &group.MsgLeaveGroup{ + GroupId: groupInfo.Id, + Address: leaver.AddressBech32, + } + return []simsx.SimAccount{leaver}, msg + } +} + +func genGroupMembersX(testData *simsx.ChainDataSource, reporter simsx.SimulationReporter, filters ...simsx.SimAccountFilter) []group.MemberRequest { + r := testData.Rand() + membersCount := r.Intn(5) + 1 + members := make([]group.MemberRequest, membersCount) + uniqueAccountsFilter := simsx.UniqueAccounts() + for i := 0; i < membersCount && !reporter.IsSkipped(); i++ { + m := testData.AnyAccount(reporter, append(filters, uniqueAccountsFilter)...) + members[i] = group.MemberRequest{ + Address: m.AddressBech32, + Weight: strconv.Itoa(r.IntInRange(1, 10)), + Metadata: r.StringN(10), + } + } + return members +} + +func randomGroupX(ctx context.Context, k keeper.Keeper, testdata *simsx.ChainDataSource, reporter simsx.SimulationReporter, s *SharedState) *group.GroupInfo { + r := testdata.Rand() + groupID := k.GetGroupSequence(ctx) + if initialGroupID := s.getMinGroupID(); initialGroupID == unsetGroupID { + s.setMinGroupID(groupID) + } else if initialGroupID < groupID { + groupID = r.Uint64InRange(initialGroupID+1, groupID+1) + } + + // when groupID is 0, it proves that SimulateMsgCreateGroup has never been called. that is, no group exists in the chain + if groupID == 0 { + reporter.Skip("no group exists") + return nil + } + + res, err := k.GroupInfo(ctx, &group.QueryGroupInfoRequest{GroupId: groupID}) + if err != nil { + reporter.Skip(err.Error()) + return nil + } + return res.Info +} + +func randomGroupPolicyX( + ctx context.Context, + testdata *simsx.ChainDataSource, + reporter simsx.SimulationReporter, + k keeper.Keeper, + s *SharedState, +) (*group.GroupInfo, *group.GroupPolicyInfo) { + for i := 0; i < 5; i++ { + groupInfo := randomGroupX(ctx, k, testdata, reporter, s) + if reporter.IsSkipped() { + return nil, nil + } + groupID := groupInfo.Id + result, err := k.GroupPoliciesByGroup(ctx, &group.QueryGroupPoliciesByGroupRequest{GroupId: groupID}) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + if len(result.GroupPolicies) != 0 { + return groupInfo, simsx.OneOf(testdata.Rand(), result.GroupPolicies) + } + } + reporter.Skip("no group policies") + return nil, nil +} diff --git a/x/group/simulation/operations.go b/x/group/simulation/operations.go deleted file mode 100644 index bab0939fddaf..000000000000 --- a/x/group/simulation/operations.go +++ /dev/null @@ -1,1508 +0,0 @@ -package simulation - -import ( - "context" - "fmt" - "math/rand" - "strings" - "sync/atomic" - "time" - - gogoprotoany "github.com/cosmos/gogoproto/types/any" - - "cosmossdk.io/core/address" - "cosmossdk.io/x/group" - "cosmossdk.io/x/group/keeper" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - cdctypes "github.com/cosmos/cosmos-sdk/codec/types" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -const unsetGroupID = 100000000000000 - -// group message types -var ( - TypeMsgCreateGroup = sdk.MsgTypeURL(&group.MsgCreateGroup{}) - TypeMsgUpdateGroupMembers = sdk.MsgTypeURL(&group.MsgUpdateGroupMembers{}) - TypeMsgUpdateGroupAdmin = sdk.MsgTypeURL(&group.MsgUpdateGroupAdmin{}) - TypeMsgUpdateGroupMetadata = sdk.MsgTypeURL(&group.MsgUpdateGroupMetadata{}) - TypeMsgCreateGroupWithPolicy = sdk.MsgTypeURL(&group.MsgCreateGroupWithPolicy{}) - TypeMsgCreateGroupPolicy = sdk.MsgTypeURL(&group.MsgCreateGroupPolicy{}) - TypeMsgUpdateGroupPolicyAdmin = sdk.MsgTypeURL(&group.MsgUpdateGroupPolicyAdmin{}) - TypeMsgUpdateGroupPolicyDecisionPolicy = sdk.MsgTypeURL(&group.MsgUpdateGroupPolicyDecisionPolicy{}) - TypeMsgUpdateGroupPolicyMetadata = sdk.MsgTypeURL(&group.MsgUpdateGroupPolicyMetadata{}) - TypeMsgSubmitProposal = sdk.MsgTypeURL(&group.MsgSubmitProposal{}) - TypeMsgWithdrawProposal = sdk.MsgTypeURL(&group.MsgWithdrawProposal{}) - TypeMsgVote = sdk.MsgTypeURL(&group.MsgVote{}) - TypeMsgExec = sdk.MsgTypeURL(&group.MsgExec{}) - TypeMsgLeaveGroup = sdk.MsgTypeURL(&group.MsgLeaveGroup{}) -) - -// Simulation operation weights constants -const ( - OpMsgCreateGroup = "op_weight_msg_create_group" - OpMsgUpdateGroupAdmin = "op_weight_msg_update_group_admin" - OpMsgUpdateGroupMetadata = "op_wieght_msg_update_group_metadata" - OpMsgUpdateGroupMembers = "op_weight_msg_update_group_members" - OpMsgCreateGroupPolicy = "op_weight_msg_create_group_account" - OpMsgCreateGroupWithPolicy = "op_weight_msg_create_group_with_policy" - OpMsgUpdateGroupPolicyAdmin = "op_weight_msg_update_group_account_admin" - OpMsgUpdateGroupPolicyDecisionPolicy = "op_weight_msg_update_group_account_decision_policy" - OpMsgUpdateGroupPolicyMetaData = "op_weight_msg_update_group_account_metadata" - OpMsgSubmitProposal = "op_weight_msg_submit_proposal" - OpMsgWithdrawProposal = "op_weight_msg_withdraw_proposal" - OpMsgVote = "op_weight_msg_vote" - OpMsgExec = "ops_weight_msg_exec" - OpMsgLeaveGroup = "ops_weight_msg_leave_group" -) - -// If update group or group policy txn's executed, `SimulateMsgVote` & `SimulateMsgExec` txn's returns `noOp`. -// That's why we have less weight for update group & group-policy txn's. -const ( - WeightMsgCreateGroup = 100 - WeightMsgCreateGroupPolicy = 50 - WeightMsgSubmitProposal = 90 - WeightMsgVote = 90 - WeightMsgExec = 90 - WeightMsgLeaveGroup = 5 - WeightMsgUpdateGroupMetadata = 5 - WeightMsgUpdateGroupAdmin = 5 - WeightMsgUpdateGroupMembers = 5 - WeightMsgUpdateGroupPolicyAdmin = 5 - WeightMsgUpdateGroupPolicyDecisionPolicy = 5 - WeightMsgUpdateGroupPolicyMetadata = 5 - WeightMsgWithdrawProposal = 20 - WeightMsgCreateGroupWithPolicy = 50 -) - -// SharedState shared state between message invocations -type SharedState struct { - minGroupID atomic.Uint64 -} - -// NewSharedState constructor -func NewSharedState() *SharedState { - r := &SharedState{} - r.setMinGroupID(unsetGroupID) - return r -} - -func (s *SharedState) getMinGroupID() uint64 { - return s.minGroupID.Load() -} - -func (s *SharedState) setMinGroupID(id uint64) { - s.minGroupID.Store(id) -} - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - registry cdctypes.InterfaceRegistry, - appParams simtypes.AppParams, cdc codec.JSONCodec, txGen client.TxConfig, - ak group.AccountKeeper, bk group.BankKeeper, k keeper.Keeper, - appCdc gogoprotoany.AnyUnpacker, -) simulation.WeightedOperations { - var ( - weightMsgCreateGroup int - weightMsgUpdateGroupAdmin int - weightMsgUpdateGroupMetadata int - weightMsgUpdateGroupMembers int - weightMsgCreateGroupPolicy int - weightMsgUpdateGroupPolicyAdmin int - weightMsgUpdateGroupPolicyDecisionPolicy int - weightMsgUpdateGroupPolicyMetadata int - weightMsgSubmitProposal int - weightMsgVote int - weightMsgExec int - weightMsgLeaveGroup int - weightMsgWithdrawProposal int - weightMsgCreateGroupWithPolicy int - ) - - appParams.GetOrGenerate(OpMsgCreateGroup, &weightMsgCreateGroup, nil, func(_ *rand.Rand) { - weightMsgCreateGroup = WeightMsgCreateGroup - }) - appParams.GetOrGenerate(OpMsgCreateGroupPolicy, &weightMsgCreateGroupPolicy, nil, func(_ *rand.Rand) { - weightMsgCreateGroupPolicy = WeightMsgCreateGroupPolicy - }) - appParams.GetOrGenerate(OpMsgLeaveGroup, &weightMsgLeaveGroup, nil, func(_ *rand.Rand) { - weightMsgLeaveGroup = WeightMsgLeaveGroup - }) - appParams.GetOrGenerate(OpMsgCreateGroupWithPolicy, &weightMsgCreateGroupWithPolicy, nil, func(_ *rand.Rand) { - weightMsgCreateGroupWithPolicy = WeightMsgCreateGroupWithPolicy - }) - appParams.GetOrGenerate(OpMsgSubmitProposal, &weightMsgSubmitProposal, nil, func(_ *rand.Rand) { - weightMsgSubmitProposal = WeightMsgSubmitProposal - }) - appParams.GetOrGenerate(OpMsgVote, &weightMsgVote, nil, func(_ *rand.Rand) { - weightMsgVote = WeightMsgVote - }) - appParams.GetOrGenerate(OpMsgExec, &weightMsgExec, nil, func(_ *rand.Rand) { - weightMsgExec = WeightMsgExec - }) - appParams.GetOrGenerate(OpMsgUpdateGroupMetadata, &weightMsgUpdateGroupMetadata, nil, func(_ *rand.Rand) { - weightMsgUpdateGroupMetadata = WeightMsgUpdateGroupMetadata - }) - appParams.GetOrGenerate(OpMsgUpdateGroupAdmin, &weightMsgUpdateGroupAdmin, nil, func(_ *rand.Rand) { - weightMsgUpdateGroupAdmin = WeightMsgUpdateGroupAdmin - }) - appParams.GetOrGenerate(OpMsgUpdateGroupMembers, &weightMsgUpdateGroupMembers, nil, func(_ *rand.Rand) { - weightMsgUpdateGroupMembers = WeightMsgUpdateGroupMembers - }) - appParams.GetOrGenerate(OpMsgUpdateGroupPolicyAdmin, &weightMsgUpdateGroupPolicyAdmin, nil, func(_ *rand.Rand) { - weightMsgUpdateGroupPolicyAdmin = WeightMsgUpdateGroupPolicyAdmin - }) - appParams.GetOrGenerate(OpMsgUpdateGroupPolicyDecisionPolicy, &weightMsgUpdateGroupPolicyDecisionPolicy, nil, func(_ *rand.Rand) { - weightMsgUpdateGroupPolicyDecisionPolicy = WeightMsgUpdateGroupPolicyDecisionPolicy - }) - appParams.GetOrGenerate(OpMsgUpdateGroupPolicyMetaData, &weightMsgUpdateGroupPolicyMetadata, nil, func(_ *rand.Rand) { - weightMsgUpdateGroupPolicyMetadata = WeightMsgUpdateGroupPolicyMetadata - }) - appParams.GetOrGenerate(OpMsgWithdrawProposal, &weightMsgWithdrawProposal, nil, func(_ *rand.Rand) { - weightMsgWithdrawProposal = WeightMsgWithdrawProposal - }) - - pCdc := codec.NewProtoCodec(registry) - - state := NewSharedState() - - // create two proposals for weightedOperations - var createProposalOps simulation.WeightedOperations - for i := 0; i < 2; i++ { - createProposalOps = append(createProposalOps, simulation.NewWeightedOperation( - weightMsgSubmitProposal, - SimulateMsgSubmitProposal(pCdc, txGen, ak, bk, k, state), - )) - } - - wPreCreateProposalOps := simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgCreateGroup, - SimulateMsgCreateGroup(pCdc, txGen, ak, bk), - ), - simulation.NewWeightedOperation( - weightMsgCreateGroupPolicy, - SimulateMsgCreateGroupPolicy(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgCreateGroupWithPolicy, - SimulateMsgCreateGroupWithPolicy(pCdc, txGen, ak, bk), - ), - } - - wPostCreateProposalOps := simulation.WeightedOperations{ - simulation.NewWeightedOperation( - WeightMsgWithdrawProposal, - SimulateMsgWithdrawProposal(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgVote, - SimulateMsgVote(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgExec, - SimulateMsgExec(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgUpdateGroupMetadata, - SimulateMsgUpdateGroupMetadata(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgUpdateGroupAdmin, - SimulateMsgUpdateGroupAdmin(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgUpdateGroupMembers, - SimulateMsgUpdateGroupMembers(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgUpdateGroupPolicyAdmin, - SimulateMsgUpdateGroupPolicyAdmin(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgUpdateGroupPolicyDecisionPolicy, - SimulateMsgUpdateGroupPolicyDecisionPolicy(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgUpdateGroupPolicyMetadata, - SimulateMsgUpdateGroupPolicyMetadata(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgLeaveGroup, - SimulateMsgLeaveGroup(pCdc, txGen, k, ak, bk, state), - ), - } - - return append(wPreCreateProposalOps, append(createProposalOps, wPostCreateProposalOps...)...) -} - -// SimulateMsgCreateGroup generates a MsgCreateGroup with random values -func SimulateMsgCreateGroup( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - acc, _ := simtypes.RandomAcc(r, accounts) - account := ak.GetAccount(ctx, acc.Address) - accAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "error getting account address"), nil, err - } - - spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "fee error"), nil, err - } - - members, err := genGroupMembers(r, accounts, ak.AddressCodec()) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "error generating group members"), nil, err - } - msg := &group.MsgCreateGroup{Admin: accAddr, Members: members, Metadata: simtypes.RandStringOfLength(r, 10)} - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgCreateGroupWithPolicy generates a MsgCreateGroupWithPolicy with random values -func SimulateMsgCreateGroupWithPolicy( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - acc, _ := simtypes.RandomAcc(r, accounts) - account := ak.GetAccount(ctx, acc.Address) - accAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "error getting account address"), nil, err - } - - spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "fee error"), nil, err - } - - members, err := genGroupMembers(r, accounts, ak.AddressCodec()) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "error generating group members"), nil, err - } - decisionPolicy := &group.ThresholdDecisionPolicy{ - Threshold: fmt.Sprintf("%d", simtypes.RandIntBetween(r, 1, 10)), - Windows: &group.DecisionPolicyWindows{ - VotingPeriod: time.Second * time.Duration(30*24*60*60), - }, - } - - msg := &group.MsgCreateGroupWithPolicy{ - Admin: accAddr, - Members: members, - GroupMetadata: simtypes.RandStringOfLength(r, 10), - GroupPolicyMetadata: simtypes.RandStringOfLength(r, 10), - GroupPolicyAsAdmin: r.Float32() < 0.5, - } - err = msg.SetDecisionPolicy(decisionPolicy) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to set decision policy"), nil, err - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupWithPolicy, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, nil - } -} - -// SimulateMsgCreateGroupPolicy generates a NewMsgCreateGroupPolicy with random values -func SimulateMsgCreateGroupPolicy( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - groupInfo, acc, account, err := randomGroup(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, ""), nil, err - } - if groupInfo == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, ""), nil, nil - } - groupID := groupInfo.Id - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, "fee error"), nil, err - } - - accAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, "error generating admin address"), nil, err - } - - msg, err := group.NewMsgCreateGroupPolicy( - accAddr, - groupID, - simtypes.RandStringOfLength(r, 10), - &group.ThresholdDecisionPolicy{ - Threshold: fmt.Sprintf("%d", simtypes.RandIntBetween(r, 1, 10)), - Windows: &group.DecisionPolicyWindows{ - VotingPeriod: time.Second * time.Duration(30*24*60*60), - }, - }, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, err.Error()), nil, err - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - fmt.Printf("ERR DELIVER %v\n", err) - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgSubmitProposal generates a NewMsgSubmitProposal with random values -func SimulateMsgSubmitProposal( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - g, groupPolicy, _, _, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, ""), nil, err - } - if g == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, "no group found"), nil, nil - } - if groupPolicy == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, "no group policy found"), nil, nil - } - groupID := g.Id - groupPolicyAddr := groupPolicy.Address - - // Return a no-op if we know the proposal cannot be created - policy, err := groupPolicy.GetDecisionPolicy() - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, ""), nil, nil - } - err = policy.Validate(*g, group.DefaultConfig()) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, ""), nil, nil - } - - // Pick a random member from the group - acc, account, err := randomMember(sdkCtx, r, k, ak, accounts, groupID) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, ""), nil, err - } - if account == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, "no group member found"), nil, nil - } - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, "fee error"), nil, err - } - - accAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, "error getting account address"), nil, err - } - - msg := &group.MsgSubmitProposal{ - GroupPolicyAddress: groupPolicyAddr, - Proposers: []string{accAddr}, - Metadata: simtypes.RandStringOfLength(r, 10), - Title: "Test Proposal", - Summary: "Summary of the proposal", - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgUpdateGroupAdmin generates a MsgUpdateGroupAdmin with random values -func SimulateMsgUpdateGroupAdmin( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - groupInfo, acc, account, err := randomGroup(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, ""), nil, err - } - if groupInfo == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, ""), nil, nil - } - groupID := groupInfo.Id - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "fee error"), nil, err - } - - if len(accounts) == 1 { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "can't set a new admin with only one account"), nil, nil - } - newAdmin, _ := simtypes.RandomAcc(r, accounts) - // disallow setting current admin as new admin - for acc.PubKey.Equals(newAdmin.PubKey) { - newAdmin, _ = simtypes.RandomAcc(r, accounts) - } - - accAddr, err := ak.AddressCodec().BytesToString(account.GetAddress()) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "error getting admin address"), nil, err - } - newAdminAddr, err := ak.AddressCodec().BytesToString(newAdmin.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "error getting new admin address"), nil, err - } - msg := &group.MsgUpdateGroupAdmin{ - GroupId: groupID, - Admin: accAddr, - NewAdmin: newAdminAddr, - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgUpdateGroupMetadata generates a MsgUpdateGroupMetadata with random values -func SimulateMsgUpdateGroupMetadata( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - groupInfo, acc, account, err := randomGroup(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, ""), nil, err - } - if groupInfo == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, ""), nil, nil - } - groupID := groupInfo.Id - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, "fee error"), nil, err - } - - adminAddr, err := ak.AddressCodec().BytesToString(account.GetAddress()) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, "error getting admin address"), nil, err - } - msg := &group.MsgUpdateGroupMetadata{ - GroupId: groupID, - Admin: adminAddr, - Metadata: simtypes.RandStringOfLength(r, 10), - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgUpdateGroupMembers generates a MsgUpdateGroupMembers with random values -func SimulateMsgUpdateGroupMembers( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - groupInfo, acc, account, err := randomGroup(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, ""), nil, err - } - if groupInfo == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, ""), nil, nil - } - groupID := groupInfo.Id - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, "fee error"), nil, err - } - - members, err := genGroupMembers(r, accounts, ak.AddressCodec()) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "error generating group members"), nil, err - } - ctx := sdk.UnwrapSDKContext(sdkCtx) - res, err := k.GroupMembers(ctx, &group.QueryGroupMembersRequest{GroupId: groupID}) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, "group members"), nil, err - } - - // set existing random group member weight to zero to remove from the group - existigMembers := res.Members - if len(existigMembers) > 0 { - memberToRemove := existigMembers[r.Intn(len(existigMembers))] - var isDuplicateMember bool - for idx, m := range members { - if m.Address == memberToRemove.Member.Address { - members[idx].Weight = "0" - isDuplicateMember = true - break - } - } - - if !isDuplicateMember { - m := memberToRemove.Member - m.Weight = "0" - members = append(members, group.MemberToMemberRequest(m)) - } - } - - adminAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, "error getting admin address"), nil, err - } - msg := &group.MsgUpdateGroupMembers{ - GroupId: groupID, - Admin: adminAddr, - MemberUpdates: members, - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgUpdateGroupPolicyAdmin generates a MsgUpdateGroupPolicyAdmin with random values -func SimulateMsgUpdateGroupPolicyAdmin( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - _, groupPolicy, acc, account, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, ""), nil, err - } - if groupPolicy == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "no group policy found"), nil, nil - } - groupPolicyAddr := groupPolicy.Address - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "fee error"), nil, err - } - - if len(accounts) == 1 { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "can't set a new admin with only one account"), nil, nil - } - newAdmin, _ := simtypes.RandomAcc(r, accounts) - // disallow setting current admin as new admin - for acc.PubKey.Equals(newAdmin.PubKey) { - newAdmin, _ = simtypes.RandomAcc(r, accounts) - } - - adminAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "error getting admin address"), nil, err - } - newAdminAddr, err := ak.AddressCodec().BytesToString(newAdmin.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "error getting new admin address"), nil, err - } - msg := &group.MsgUpdateGroupPolicyAdmin{ - Admin: adminAddr, - GroupPolicyAddress: groupPolicyAddr, - NewAdmin: newAdminAddr, - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// // SimulateMsgUpdateGroupPolicyDecisionPolicy generates a NewMsgUpdateGroupPolicyDecisionPolicy with random values -func SimulateMsgUpdateGroupPolicyDecisionPolicy( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - _, groupPolicy, acc, account, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, ""), nil, err - } - if groupPolicy == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, "no group policy found"), nil, nil - } - groupPolicyAddr := groupPolicy.Address - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, "fee error"), nil, err - } - - groupPolicyBech32, err := sdk.AccAddressFromBech32(groupPolicyAddr) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, fmt.Sprintf("fail to decide bech32 address: %s", err.Error())), nil, nil - } - - accAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, "error getting admin address"), nil, err - } - groupPolicyStrAddr, err := ak.AddressCodec().BytesToString(groupPolicyBech32) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, "error group policy admin address"), nil, err - } - - msg, err := group.NewMsgUpdateGroupPolicyDecisionPolicy(accAddr, groupPolicyStrAddr, &group.ThresholdDecisionPolicy{ - Threshold: fmt.Sprintf("%d", simtypes.RandIntBetween(r, 1, 10)), - Windows: &group.DecisionPolicyWindows{ - VotingPeriod: time.Second * time.Duration(simtypes.RandIntBetween(r, 100, 1000)), - }, - }) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, err.Error()), nil, err - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// // SimulateMsgUpdateGroupPolicyMetadata generates a MsgUpdateGroupPolicyMetadata with random values -func SimulateMsgUpdateGroupPolicyMetadata( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - _, groupPolicy, acc, account, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, ""), nil, err - } - if groupPolicy == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "no group policy found"), nil, nil - } - groupPolicyAddr := groupPolicy.Address - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "fee error"), nil, err - } - - adminAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "error getting admin address"), nil, err - } - msg := &group.MsgUpdateGroupPolicyMetadata{ - Admin: adminAddr, - GroupPolicyAddress: groupPolicyAddr, - Metadata: simtypes.RandStringOfLength(r, 10), - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgWithdrawProposal generates a MsgWithdrawProposal with random values -func SimulateMsgWithdrawProposal( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - g, groupPolicy, _, _, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, ""), nil, err - } - if g == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "no group found"), nil, nil - } - if groupPolicy == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "no group policy found"), nil, nil - } - - groupPolicyAddr := groupPolicy.Address - policy, err := groupPolicy.GetDecisionPolicy() - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, err.Error()), nil, nil - } - err = policy.Validate(*g, group.DefaultConfig()) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, err.Error()), nil, nil - } - - proposalsResult, err := k.ProposalsByGroupPolicy(sdkCtx, &group.QueryProposalsByGroupPolicyRequest{Address: groupPolicyAddr}) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "fail to query group info"), nil, err - } - - proposals := proposalsResult.GetProposals() - if len(proposals) == 0 { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "no proposals found"), nil, nil - } - - var proposal *group.Proposal - proposalID := -1 - - for _, p := range proposals { - if p.Status == group.PROPOSAL_STATUS_SUBMITTED { - timeout := p.VotingPeriodEnd - proposal = p - proposalID = int(p.Id) - if timeout.Before(sdkCtx.HeaderInfo().Time) || timeout.Equal(sdkCtx.HeaderInfo().Time) { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "voting period ended: skipping"), nil, nil - } - break - } - } - - // return no-op if no proposal found - if proposalID == -1 { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "no proposals found"), nil, nil - } - - // select a random proposer - proposers := proposal.Proposers - n := randIntInRange(r, len(proposers)) - proposerIdx, err := findAccount(accounts, proposers[n], ak.AddressCodec()) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "could not find account"), nil, err - } - proposer := accounts[proposerIdx] - proposerAcc := ak.GetAccount(sdkCtx, proposer.Address) - - spendableCoins := bk.SpendableCoins(sdkCtx, proposer.Address) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "fee error"), nil, err - } - - proposerAddr, err := ak.AddressCodec().BytesToString(proposer.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "error getting voter address"), nil, err - } - - msg := &group.MsgWithdrawProposal{ - ProposalId: uint64(proposalID), - Address: proposerAddr, - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{proposerAcc.GetAccountNumber()}, - []uint64{proposerAcc.GetSequence()}, - proposer.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - if strings.Contains(err.Error(), "group was modified") || strings.Contains(err.Error(), "group policy was modified") { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "no-op:group/group-policy was modified"), nil, nil - } - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgVote generates a MsgVote with random values -func SimulateMsgVote( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - g, groupPolicy, _, _, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, ""), nil, err - } - if g == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no group found"), nil, nil - } - if groupPolicy == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no group policy found"), nil, nil - } - groupPolicyAddr := groupPolicy.Address - - // Pick a random member from the group - acc, account, err := randomMember(sdkCtx, r, k, ak, accounts, g.Id) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, ""), nil, err - } - if account == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no group member found"), nil, nil - } - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "fee error"), nil, err - } - - proposalsResult, err := k.ProposalsByGroupPolicy(sdkCtx, &group.QueryProposalsByGroupPolicyRequest{Address: groupPolicyAddr}) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "fail to query group info"), nil, err - } - proposals := proposalsResult.GetProposals() - if len(proposals) == 0 { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no proposals found"), nil, nil - } - - proposalID := -1 - - for _, p := range proposals { - if p.Status == group.PROPOSAL_STATUS_SUBMITTED { - timeout := p.VotingPeriodEnd - proposalID = int(p.Id) - if timeout.Before(sdkCtx.HeaderInfo().Time) || timeout.Equal(sdkCtx.HeaderInfo().Time) { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "voting period ended: skipping"), nil, nil - } - break - } - } - - // return no-op if no proposal found - if proposalID == -1 { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no proposals found"), nil, nil - } - - voterAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "error getting voter address"), nil, err - } - - // Ensure member hasn't already voted - res, _ := k.VoteByProposalVoter(sdkCtx, &group.QueryVoteByProposalVoterRequest{ - Voter: voterAddr, - ProposalId: uint64(proposalID), - }) - if res != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "member has already voted"), nil, nil - } - - msg := &group.MsgVote{ - ProposalId: uint64(proposalID), - Voter: voterAddr, - Option: group.VOTE_OPTION_YES, - Metadata: simtypes.RandStringOfLength(r, 10), - } - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - if strings.Contains(err.Error(), "group was modified") || strings.Contains(err.Error(), "group policy was modified") { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "no-op:group/group-policy was modified"), nil, nil - } - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// // SimulateMsgExec generates a MsgExec with random values -func SimulateMsgExec( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - _, groupPolicy, acc, account, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, ""), nil, err - } - if groupPolicy == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "no group policy found"), nil, nil - } - groupPolicyAddr := groupPolicy.Address - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "fee error"), nil, err - } - - proposalsResult, err := k.ProposalsByGroupPolicy(sdkCtx, &group.QueryProposalsByGroupPolicyRequest{Address: groupPolicyAddr}) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "fail to query group info"), nil, err - } - proposals := proposalsResult.GetProposals() - if len(proposals) == 0 { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "no proposals found"), nil, nil - } - - proposalID := -1 - - for _, proposal := range proposals { - if proposal.Status == group.PROPOSAL_STATUS_ACCEPTED { - proposalID = int(proposal.Id) - break - } - } - - // return no-op if no proposal found - if proposalID == -1 { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "no proposals found"), nil, nil - } - - accAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "error getting executor address"), nil, err - } - msg := &group.MsgExec{ - ProposalId: uint64(proposalID), - Executor: accAddr, - } - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - if strings.Contains(err.Error(), "group was modified") || strings.Contains(err.Error(), "group policy was modified") { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "no-op:group/group-policy was modified"), nil, nil - } - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgLeaveGroup generates a MsgLeaveGroup with random values -func SimulateMsgLeaveGroup( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - k keeper.Keeper, - ak group.AccountKeeper, - bk group.BankKeeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - groupInfo, policyInfo, _, _, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, ""), nil, err - } - - if policyInfo == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, "no policy found"), nil, nil - } - - // Pick a random member from the group - acc, account, err := randomMember(sdkCtx, r, k, ak, accounts, groupInfo.Id) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, ""), nil, err - } - if account == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, "no group member found"), nil, nil - } - - spendableCoins := bk.SpendableCoins(sdkCtx, acc.Address) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, "fee error"), nil, err - } - - accAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, "error getting account address"), nil, err - } - msg := &group.MsgLeaveGroup{ - Address: accAddr, - GroupId: groupInfo.Id, - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), err.Error()), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -func randomGroup(r *rand.Rand, k keeper.Keeper, ak group.AccountKeeper, - ctx sdk.Context, accounts []simtypes.Account, s *SharedState, -) (groupInfo *group.GroupInfo, acc simtypes.Account, account sdk.AccountI, err error) { - groupID := k.GetGroupSequence(ctx) - - if initialGroupID := s.getMinGroupID(); initialGroupID == unsetGroupID { - s.setMinGroupID(groupID) - } else if initialGroupID < groupID { - groupID = uint64(simtypes.RandIntBetween(r, int(initialGroupID+1), int(groupID+1))) - } - - // when groupID is 0, it proves that SimulateMsgCreateGroup has never been called. that is, no group exists in the chain - if groupID == 0 { - return nil, simtypes.Account{}, nil, nil - } - - res, err := k.GroupInfo(ctx, &group.QueryGroupInfoRequest{GroupId: groupID}) - if err != nil { - return nil, simtypes.Account{}, nil, err - } - - groupInfo = res.Info - groupAdmin := groupInfo.Admin - found := -1 - for i := range accounts { - addr, err := ak.AddressCodec().BytesToString(accounts[i].Address) - if err != nil { - return nil, simtypes.Account{}, nil, err - } - if addr == groupAdmin { - found = i - break - } - } - if found < 0 { - return nil, simtypes.Account{}, nil, nil - } - acc = accounts[found] - account = ak.GetAccount(ctx, acc.Address) - return groupInfo, acc, account, nil -} - -func randomGroupPolicy(r *rand.Rand, k keeper.Keeper, ak group.AccountKeeper, - ctx sdk.Context, accounts []simtypes.Account, s *SharedState, -) (groupInfo *group.GroupInfo, groupPolicyInfo *group.GroupPolicyInfo, acc simtypes.Account, account sdk.AccountI, err error) { - groupInfo, _, _, err = randomGroup(r, k, ak, ctx, accounts, s) - if err != nil { - return nil, nil, simtypes.Account{}, nil, err - } - if groupInfo == nil { - return nil, nil, simtypes.Account{}, nil, nil - } - groupID := groupInfo.Id - - result, err := k.GroupPoliciesByGroup(ctx, &group.QueryGroupPoliciesByGroupRequest{GroupId: groupID}) - if err != nil { - return groupInfo, nil, simtypes.Account{}, nil, err - } - - n := randIntInRange(r, len(result.GroupPolicies)) - if n < 0 { - return groupInfo, nil, simtypes.Account{}, nil, nil - } - groupPolicyInfo = result.GroupPolicies[n] - - idx, err := findAccount(accounts, groupPolicyInfo.Admin, ak.AddressCodec()) - if err != nil { - return groupInfo, nil, simtypes.Account{}, nil, nil - } - - if idx < 0 { - return groupInfo, nil, simtypes.Account{}, nil, nil - } - acc = accounts[idx] - account = ak.GetAccount(ctx, acc.Address) - return groupInfo, groupPolicyInfo, acc, account, nil -} - -func randomMember(ctx context.Context, r *rand.Rand, k keeper.Keeper, ak group.AccountKeeper, - accounts []simtypes.Account, groupID uint64, -) (acc simtypes.Account, account sdk.AccountI, err error) { - res, err := k.GroupMembers(ctx, &group.QueryGroupMembersRequest{ - GroupId: groupID, - }) - if err != nil { - return simtypes.Account{}, nil, err - } - n := randIntInRange(r, len(res.Members)) - if n < 0 { - return simtypes.Account{}, nil, err - } - idx, err := findAccount(accounts, res.Members[n].Member.Address, ak.AddressCodec()) - if err != nil { - return simtypes.Account{}, nil, err - } - if idx < 0 { - return simtypes.Account{}, nil, err - } - acc = accounts[idx] - account = ak.GetAccount(sdk.UnwrapSDKContext(ctx), acc.Address) - return acc, account, nil -} - -func randIntInRange(r *rand.Rand, l int) int { - if l == 0 { - return -1 - } - if l == 1 { - return 0 - } - return simtypes.RandIntBetween(r, 0, l-1) -} - -func findAccount(accounts []simtypes.Account, addr string, addressCodec address.Codec) (idx int, err error) { - idx = -1 - for i := range accounts { - accAddr, err := addressCodec.BytesToString(accounts[i].Address) - if err != nil { - return idx, err - } - if accAddr == addr { - idx = i - break - } - } - return idx, err -} - -func genGroupMembers(r *rand.Rand, accounts []simtypes.Account, addressCodec address.Codec) ([]group.MemberRequest, error) { - if len(accounts) == 1 { - addr, err := addressCodec.BytesToString(accounts[0].Address) - if err != nil { - return nil, err - } - return []group.MemberRequest{ - { - Address: addr, - Weight: fmt.Sprintf("%d", simtypes.RandIntBetween(r, 1, 10)), - Metadata: simtypes.RandStringOfLength(r, 10), - }, - }, nil - } - - max := 5 - if len(accounts) < max { - max = len(accounts) - } - - membersLen := simtypes.RandIntBetween(r, 1, max) - members := make([]group.MemberRequest, membersLen) - - for i := 0; i < membersLen; i++ { - addr, err := addressCodec.BytesToString(accounts[i].Address) - if err != nil { - return nil, err - } - members[i] = group.MemberRequest{ - Address: addr, - Weight: fmt.Sprintf("%d", simtypes.RandIntBetween(r, 1, 10)), - Metadata: simtypes.RandStringOfLength(r, 10), - } - } - - return members, nil -} diff --git a/x/group/simulation/operations_test.go b/x/group/simulation/operations_test.go deleted file mode 100644 index 598e6892b1fa..000000000000 --- a/x/group/simulation/operations_test.go +++ /dev/null @@ -1,759 +0,0 @@ -package simulation_test - -import ( - "math/rand" - "testing" - "time" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/depinject" - "cosmossdk.io/log" - bankkeeper "cosmossdk.io/x/bank/keeper" - "cosmossdk.io/x/bank/testutil" - banktypes "cosmossdk.io/x/bank/types" - "cosmossdk.io/x/group" - groupkeeper "cosmossdk.io/x/group/keeper" - "cosmossdk.io/x/group/simulation" - grouptestutil "cosmossdk.io/x/group/testutil" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/runtime" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" -) - -type SimTestSuite struct { - suite.Suite - - ctx sdk.Context - app *runtime.App - codec codec.Codec - interfaceRegistry codectypes.InterfaceRegistry - txConfig client.TxConfig - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.Keeper - groupKeeper groupkeeper.Keeper -} - -func (suite *SimTestSuite) SetupTest() { - app, err := simtestutil.Setup( - depinject.Configs( - grouptestutil.AppConfig, - depinject.Supply(log.NewNopLogger()), - ), - &suite.codec, - &suite.interfaceRegistry, - &suite.txConfig, - &suite.accountKeeper, - &suite.bankKeeper, - &suite.groupKeeper, - ) - suite.Require().NoError(err) - - suite.app = app - suite.ctx = app.BaseApp.NewContext(false) -} - -func (suite *SimTestSuite) TestWeightedOperations() { - cdc := suite.codec - appParams := make(simtypes.AppParams) - - weightedOps := simulation.WeightedOperations(suite.interfaceRegistry, appParams, cdc, suite.txConfig, suite.accountKeeper, - suite.bankKeeper, suite.groupKeeper, cdc, - ) - - s := rand.NewSource(2) - r := rand.New(s) - accs := suite.getTestingAccounts(r, 3) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {simulation.WeightMsgCreateGroup, group.ModuleName, simulation.TypeMsgCreateGroup}, - {simulation.WeightMsgCreateGroupPolicy, group.ModuleName, simulation.TypeMsgCreateGroupPolicy}, - {simulation.WeightMsgCreateGroupWithPolicy, group.ModuleName, simulation.TypeMsgCreateGroupWithPolicy}, - {simulation.WeightMsgSubmitProposal, group.ModuleName, simulation.TypeMsgSubmitProposal}, - {simulation.WeightMsgSubmitProposal, group.ModuleName, simulation.TypeMsgSubmitProposal}, - {simulation.WeightMsgWithdrawProposal, group.ModuleName, simulation.TypeMsgWithdrawProposal}, - {simulation.WeightMsgVote, group.ModuleName, simulation.TypeMsgVote}, - {simulation.WeightMsgExec, group.ModuleName, simulation.TypeMsgExec}, - {simulation.WeightMsgUpdateGroupMetadata, group.ModuleName, simulation.TypeMsgUpdateGroupMetadata}, - {simulation.WeightMsgUpdateGroupAdmin, group.ModuleName, simulation.TypeMsgUpdateGroupAdmin}, - {simulation.WeightMsgUpdateGroupMembers, group.ModuleName, simulation.TypeMsgUpdateGroupMembers}, - {simulation.WeightMsgUpdateGroupPolicyAdmin, group.ModuleName, simulation.TypeMsgUpdateGroupPolicyAdmin}, - {simulation.WeightMsgUpdateGroupPolicyDecisionPolicy, group.ModuleName, simulation.TypeMsgUpdateGroupPolicyDecisionPolicy}, - {simulation.WeightMsgUpdateGroupPolicyMetadata, group.ModuleName, simulation.TypeMsgUpdateGroupPolicyMetadata}, - {simulation.WeightMsgLeaveGroup, group.ModuleName, simulation.TypeMsgLeaveGroup}, - } - - for i, w := range weightedOps { - operationMsg, _, err := w.Op()(r, suite.app.BaseApp, suite.ctx, accs, "") - suite.Require().NoError(err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - suite.Require().Equal(expected[i].weight, w.Weight(), "weight should be the same") - suite.Require().Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - suite.Require().Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { - accounts := simtypes.RandomAccounts(r, n) - - initAmt := sdk.TokensFromConsensusPower(200, sdk.DefaultPowerReduction) - initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) - - // add coins to the accounts - for _, account := range accounts { - acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, account.Address) - suite.accountKeeper.SetAccount(suite.ctx, acc) - suite.Require().NoError(testutil.FundAccount(suite.ctx, suite.bankKeeper, account.Address, initCoins)) - } - - return accounts -} - -func (suite *SimTestSuite) TestSimulateCreateGroup() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 1) - - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgCreateGroup(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgCreateGroup - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(accAddr, msg.Admin) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateCreateGroupWithPolicy() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 1) - - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgCreateGroupWithPolicy(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgCreateGroupWithPolicy - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(accAddr, msg.Admin) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateCreateGroupPolicy() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 1) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - _, err = suite.groupKeeper.CreateGroup(suite.ctx, - &group.MsgCreateGroup{ - Admin: accAddr, - Members: []group.MemberRequest{ - { - Address: accAddr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgCreateGroupPolicy(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgCreateGroupPolicy - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(accAddr, msg.Admin) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateSubmitProposal() { - // setup 1 account - s := rand.NewSource(2) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 1) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - ctx := suite.ctx - groupRes, err := suite.groupKeeper.CreateGroup(ctx, - &group.MsgCreateGroup{ - Admin: accAddr, - Members: []group.MemberRequest{ - { - Address: accAddr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // setup a group account - accountReq := &group.MsgCreateGroupPolicy{ - Admin: accAddr, - GroupId: groupRes.GroupId, - } - err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour, 0)) - suite.Require().NoError(err) - groupPolicyRes, err := suite.groupKeeper.CreateGroupPolicy(ctx, accountReq) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgSubmitProposal(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgSubmitProposal - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(groupPolicyRes.Address, msg.GroupPolicyAddress) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestWithdrawProposal() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - ctx := suite.ctx - addr := accAddr - groupRes, err := suite.groupKeeper.CreateGroup(ctx, - &group.MsgCreateGroup{ - Admin: addr, - Members: []group.MemberRequest{ - { - Address: addr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // setup a group account - accountReq := &group.MsgCreateGroupPolicy{ - Admin: addr, - GroupId: groupRes.GroupId, - } - err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour, 0)) - suite.Require().NoError(err) - groupPolicyRes, err := suite.groupKeeper.CreateGroupPolicy(ctx, accountReq) - suite.Require().NoError(err) - - // setup a proposal - proposalReq, err := group.NewMsgSubmitProposal(groupPolicyRes.Address, []string{addr}, []sdk.Msg{ - &banktypes.MsgSend{ - FromAddress: groupPolicyRes.Address, - ToAddress: addr, - Amount: sdk.Coins{sdk.NewInt64Coin("token", 100)}, - }, - }, "", 0, "MsgSend", "this is a test proposal") - suite.Require().NoError(err) - _, err = suite.groupKeeper.SubmitProposal(ctx, proposalReq) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgWithdrawProposal(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgWithdrawProposal - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(addr, msg.Address) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateVote() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 1) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - ctx := suite.ctx - addr := accAddr - groupRes, err := suite.groupKeeper.CreateGroup(ctx, - &group.MsgCreateGroup{ - Admin: addr, - Members: []group.MemberRequest{ - { - Address: addr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // setup a group account - accountReq := &group.MsgCreateGroupPolicy{ - Admin: addr, - GroupId: groupRes.GroupId, - Metadata: "", - } - err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour, 0)) - suite.Require().NoError(err) - groupPolicyRes, err := suite.groupKeeper.CreateGroupPolicy(ctx, accountReq) - suite.Require().NoError(err) - - // setup a proposal - proposalReq, err := group.NewMsgSubmitProposal(groupPolicyRes.Address, []string{addr}, []sdk.Msg{ - &banktypes.MsgSend{ - FromAddress: groupPolicyRes.Address, - ToAddress: addr, - Amount: sdk.Coins{sdk.NewInt64Coin("token", 100)}, - }, - }, "", 0, "MsgSend", "this is a test proposal") - suite.Require().NoError(err) - _, err = suite.groupKeeper.SubmitProposal(ctx, proposalReq) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgVote(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgVote - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(addr, msg.Voter) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateExec() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 1) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - ctx := suite.ctx - addr := accAddr - groupRes, err := suite.groupKeeper.CreateGroup(ctx, - &group.MsgCreateGroup{ - Admin: addr, - Members: []group.MemberRequest{ - { - Address: addr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // setup a group account - accountReq := &group.MsgCreateGroupPolicy{ - Admin: addr, - GroupId: groupRes.GroupId, - } - err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour, 0)) - suite.Require().NoError(err) - groupPolicyRes, err := suite.groupKeeper.CreateGroupPolicy(ctx, accountReq) - suite.Require().NoError(err) - - // setup a proposal - proposalReq, err := group.NewMsgSubmitProposal(groupPolicyRes.Address, []string{addr}, []sdk.Msg{ - &banktypes.MsgSend{ - FromAddress: groupPolicyRes.Address, - ToAddress: addr, - Amount: sdk.Coins{sdk.NewInt64Coin("token", 100)}, - }, - }, "", 0, "MsgSend", "this is a test proposal") - suite.Require().NoError(err) - proposalRes, err := suite.groupKeeper.SubmitProposal(ctx, proposalReq) - suite.Require().NoError(err) - - // vote - _, err = suite.groupKeeper.Vote(ctx, &group.MsgVote{ - ProposalId: proposalRes.ProposalId, - Voter: addr, - Option: group.VOTE_OPTION_YES, - Exec: 1, - }) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgExec(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgExec - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(addr, msg.Executor) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateUpdateGroupAdmin() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - _, err = suite.groupKeeper.CreateGroup(suite.ctx, - &group.MsgCreateGroup{ - Admin: accAddr, - Members: []group.MemberRequest{ - { - Address: accAddr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgUpdateGroupAdmin(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgUpdateGroupAdmin - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(accAddr, msg.Admin) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateUpdateGroupMetadata() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - _, err = suite.groupKeeper.CreateGroup(suite.ctx, - &group.MsgCreateGroup{ - Admin: accAddr, - Members: []group.MemberRequest{ - { - Address: accAddr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgUpdateGroupMetadata(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgUpdateGroupMetadata - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(accAddr, msg.Admin) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateUpdateGroupMembers() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - _, err = suite.groupKeeper.CreateGroup(suite.ctx, - &group.MsgCreateGroup{ - Admin: accAddr, - Members: []group.MemberRequest{ - { - Address: accAddr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgUpdateGroupMembers(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgUpdateGroupMembers - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(accAddr, msg.Admin) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateUpdateGroupPolicyAdmin() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - ctx := suite.ctx - groupRes, err := suite.groupKeeper.CreateGroup(ctx, - &group.MsgCreateGroup{ - Admin: accAddr, - Members: []group.MemberRequest{ - { - Address: accAddr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // setup a group account - accountReq := &group.MsgCreateGroupPolicy{ - Admin: accAddr, - GroupId: groupRes.GroupId, - } - err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour, 0)) - suite.Require().NoError(err) - groupPolicyRes, err := suite.groupKeeper.CreateGroupPolicy(ctx, accountReq) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgUpdateGroupPolicyAdmin(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgUpdateGroupPolicyAdmin - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(groupPolicyRes.Address, msg.GroupPolicyAddress) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateUpdateGroupPolicyDecisionPolicy() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - ctx := suite.ctx - groupRes, err := suite.groupKeeper.CreateGroup(ctx, - &group.MsgCreateGroup{ - Admin: accAddr, - Members: []group.MemberRequest{ - { - Address: accAddr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // setup a group account - accountReq := &group.MsgCreateGroupPolicy{ - Admin: accAddr, - GroupId: groupRes.GroupId, - } - err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour, 0)) - suite.Require().NoError(err) - groupPolicyRes, err := suite.groupKeeper.CreateGroupPolicy(ctx, accountReq) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgUpdateGroupPolicyDecisionPolicy(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgUpdateGroupPolicyDecisionPolicy - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(groupPolicyRes.Address, msg.GroupPolicyAddress) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateUpdateGroupPolicyMetadata() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - ctx := suite.ctx - groupRes, err := suite.groupKeeper.CreateGroup(ctx, - &group.MsgCreateGroup{ - Admin: accAddr, - Members: []group.MemberRequest{ - { - Address: accAddr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // setup a group account - accountReq := &group.MsgCreateGroupPolicy{ - Admin: accAddr, - GroupId: groupRes.GroupId, - } - err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour, 0)) - suite.Require().NoError(err) - groupPolicyRes, err := suite.groupKeeper.CreateGroupPolicy(ctx, accountReq) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgUpdateGroupPolicyMetadata(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgUpdateGroupPolicyMetadata - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(groupPolicyRes.Address, msg.GroupPolicyAddress) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateLeaveGroup() { - s := rand.NewSource(1) - r := rand.New(s) - require := suite.Require() - - // setup 4 account - accounts := suite.getTestingAccounts(r, 4) - admin := accounts[0] - adminAddr, err := suite.accountKeeper.AddressCodec().BytesToString(admin.Address) - suite.Require().NoError(err) - member1, err := suite.accountKeeper.AddressCodec().BytesToString(accounts[1].Address) - suite.Require().NoError(err) - member2, err := suite.accountKeeper.AddressCodec().BytesToString(accounts[2].Address) - suite.Require().NoError(err) - member3, err := suite.accountKeeper.AddressCodec().BytesToString(accounts[3].Address) - suite.Require().NoError(err) - - // setup a group - ctx := suite.ctx - groupRes, err := suite.groupKeeper.CreateGroup(ctx, - &group.MsgCreateGroup{ - Admin: adminAddr, - Members: []group.MemberRequest{ - { - Address: member1, - Weight: "1", - }, - { - Address: member2, - Weight: "2", - }, - { - Address: member3, - Weight: "1", - }, - }, - }, - ) - require.NoError(err) - - // setup a group account - accountReq := &group.MsgCreateGroupPolicy{ - Admin: adminAddr, - GroupId: groupRes.GroupId, - Metadata: "", - } - require.NoError(accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("3", time.Hour, time.Hour))) - _, err = suite.groupKeeper.CreateGroupPolicy(ctx, accountReq) - require.NoError(err) - - // execute operation - op := simulation.SimulateMsgLeaveGroup(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.groupKeeper, suite.accountKeeper, suite.bankKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgLeaveGroup - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(groupRes.GroupId, msg.GroupId) - suite.Require().Len(futureOperations, 0) -} - -func TestSimTestSuite(t *testing.T) { - suite.Run(t, new(SimTestSuite)) -} diff --git a/x/mint/go.mod b/x/mint/go.mod index 5bbfae401ba9..c2ac3ea7376e 100644 --- a/x/mint/go.mod +++ b/x/mint/go.mod @@ -5,7 +5,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 @@ -23,13 +23,13 @@ require ( github.com/stretchr/testify v1.9.0 google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 google.golang.org/grpc v1.66.2 - gotest.tools/v3 v3.5.1 + gotest.tools/v3 v3.5.1 // indirect ) require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -118,7 +118,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/x/mint/go.sum b/x/mint/go.sum index a658644fd79f..5b3cf3f73e5b 100644 --- a/x/mint/go.sum +++ b/x/mint/go.sum @@ -6,8 +6,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -402,8 +402,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/mint/keeper/msg_server_test.go b/x/mint/keeper/msg_server_test.go index 10423e26e2c6..602b4a2fbf36 100644 --- a/x/mint/keeper/msg_server_test.go +++ b/x/mint/keeper/msg_server_test.go @@ -61,7 +61,6 @@ func (s *KeeperTestSuite) TestUpdateParams() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { _, err := s.msgServer.UpdateParams(s.ctx, tc.request) if tc.expectErr { diff --git a/x/mint/module.go b/x/mint/module.go index fa27a6838df2..826dba01f6fc 100644 --- a/x/mint/module.go +++ b/x/mint/module.go @@ -16,6 +16,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" + simsx "github.com/cosmos/cosmos-sdk/simsx" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) @@ -168,17 +169,12 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { simulation.RandomizedGenState(simState) } -// ProposalMsgs returns msgs used for governance proposals for simulations. -func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { - return simulation.ProposalMsgs() +// ProposalMsgsX returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_update_params", 100), simulation.MsgUpdateParamsFactory()) } // RegisterStoreDecoder registers a decoder for mint module's types. func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[types.StoreKey] = simtypes.NewStoreDecoderFuncFromCollectionsSchema(am.keeper.Schema) } - -// WeightedOperations doesn't return any mint module operation. -func (AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { - return nil -} diff --git a/x/mint/simulation/genesis.go b/x/mint/simulation/genesis.go index 9933efa1971d..c234d27345cf 100644 --- a/x/mint/simulation/genesis.go +++ b/x/mint/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" "cosmossdk.io/math" @@ -70,10 +68,5 @@ func RandomizedGenState(simState *module.SimulationState) { mintGenesis := types.NewGenesisState(types.InitialMinter(inflation), params) - bz, err := json.MarshalIndent(&mintGenesis, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated minting parameters:\n%s\n", bz) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(mintGenesis) } diff --git a/x/mint/simulation/msg_factory.go b/x/mint/simulation/msg_factory.go new file mode 100644 index 000000000000..45c96359f61e --- /dev/null +++ b/x/mint/simulation/msg_factory.go @@ -0,0 +1,29 @@ +package simulation + +import ( + "context" + + sdkmath "cosmossdk.io/math" + "cosmossdk.io/x/mint/types" + + "github.com/cosmos/cosmos-sdk/simsx" +) + +// MsgUpdateParamsFactory creates a gov proposal for param updates +func MsgUpdateParamsFactory() simsx.SimMsgFactoryFn[*types.MsgUpdateParams] { + return func(_ context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgUpdateParams) { + r := testData.Rand() + params := types.DefaultParams() + params.BlocksPerYear = r.Uint64InRange(1, 1_000_000) + params.GoalBonded = sdkmath.LegacyNewDecWithPrec(int64(r.IntInRange(1, 100)), 2) + params.InflationMin = sdkmath.LegacyNewDecWithPrec(int64(r.IntInRange(1, 50)), 2) + params.InflationMax = sdkmath.LegacyNewDecWithPrec(int64(r.IntInRange(50, 100)), 2) + params.InflationRateChange = sdkmath.LegacyNewDecWithPrec(int64(r.IntInRange(1, 100)), 2) + params.MintDenom = r.StringN(10) + + return nil, &types.MsgUpdateParams{ + Authority: testData.ModuleAccountAddress(reporter, "gov"), + Params: params, + } + } +} diff --git a/x/mint/simulation/proposals_test.go b/x/mint/simulation/proposals_test.go deleted file mode 100644 index abc470a76d81..000000000000 --- a/x/mint/simulation/proposals_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package simulation_test - -import ( - "context" - "math/rand" - "testing" - - "gotest.tools/v3/assert" - - sdkmath "cosmossdk.io/math" - "cosmossdk.io/x/mint/simulation" - "cosmossdk.io/x/mint/types" - - codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" -) - -func TestProposalMsgs(t *testing.T) { - ac := codectestutil.CodecOptions{}.GetAddressCodec() - // initialize parameters - s := rand.NewSource(1) - r := rand.New(s) - - accounts := simtypes.RandomAccounts(r, 3) - - // execute ProposalMsgs function - weightedProposalMsgs := simulation.ProposalMsgs() - assert.Assert(t, len(weightedProposalMsgs) == 1) - - w0 := weightedProposalMsgs[0] - - // tests w0 interface: - assert.Equal(t, simulation.OpWeightMsgUpdateParams, w0.AppParamsKey()) - assert.Equal(t, simulation.DefaultWeightMsgUpdateParams, w0.DefaultWeight()) - - msg, err := w0.MsgSimulatorFn()(context.Background(), r, accounts, ac) - assert.NilError(t, err) - msgUpdateParams, ok := msg.(*types.MsgUpdateParams) - assert.Assert(t, ok) - - authority, err := ac.BytesToString(address.Module("gov")) - assert.NilError(t, err) - - assert.Equal(t, authority, msgUpdateParams.Authority) - assert.Equal(t, uint64(122877), msgUpdateParams.Params.BlocksPerYear) - assert.DeepEqual(t, sdkmath.LegacyNewDecWithPrec(95, 2), msgUpdateParams.Params.GoalBonded) - assert.DeepEqual(t, sdkmath.LegacyNewDecWithPrec(94, 2), msgUpdateParams.Params.InflationMax) - assert.DeepEqual(t, sdkmath.LegacyNewDecWithPrec(23, 2), msgUpdateParams.Params.InflationMin) - assert.DeepEqual(t, sdkmath.LegacyNewDecWithPrec(89, 2), msgUpdateParams.Params.InflationRateChange) - assert.Equal(t, "XhhuTSkuxK", msgUpdateParams.Params.MintDenom) -} diff --git a/x/nft/go.mod b/x/nft/go.mod index d312004db04f..ff38e15bdbc3 100644 --- a/x/nft/go.mod +++ b/x/nft/go.mod @@ -4,7 +4,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 @@ -26,7 +26,7 @@ require ( buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -119,7 +119,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/x/nft/go.sum b/x/nft/go.sum index a658644fd79f..5b3cf3f73e5b 100644 --- a/x/nft/go.sum +++ b/x/nft/go.sum @@ -6,8 +6,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -402,8 +402,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/nft/module/module.go b/x/nft/module/module.go index 70672dbab19a..16b82baf2a23 100644 --- a/x/nft/module/module.go +++ b/x/nft/module/module.go @@ -17,6 +17,7 @@ import ( sdkclient "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/simsx" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) @@ -130,11 +131,6 @@ func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[keeper.StoreKey] = simulation.NewDecodeStore(am.cdc) } -// WeightedOperations returns the all the nft module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - am.registry, - simState.AppParams, simState.Cdc, simState.TxConfig, - am.accountKeeper, am.bankKeeper, am.keeper, - ) +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_send", 100), simulation.MsgSendFactory(am.keeper)) } diff --git a/x/nft/simulation/decoder_test.go b/x/nft/simulation/decoder_test.go index 7498ee7e8f58..a9dfed8862ed 100644 --- a/x/nft/simulation/decoder_test.go +++ b/x/nft/simulation/decoder_test.go @@ -75,7 +75,6 @@ func TestDecodeStore(t *testing.T) { } for i, tt := range tests { - i, tt := i, tt t.Run(tt.name, func(t *testing.T) { if tt.expectErr { require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) diff --git a/x/nft/simulation/msg_factory.go b/x/nft/simulation/msg_factory.go new file mode 100644 index 000000000000..14db2666dee9 --- /dev/null +++ b/x/nft/simulation/msg_factory.go @@ -0,0 +1,66 @@ +package simulation + +import ( + "context" + + "cosmossdk.io/x/nft" + "cosmossdk.io/x/nft/keeper" + + "github.com/cosmos/cosmos-sdk/simsx" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func MsgSendFactory(k keeper.Keeper) simsx.SimMsgFactoryFn[*nft.MsgSend] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *nft.MsgSend) { + from := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + to := testData.AnyAccount(reporter, simsx.ExcludeAccounts(from)) + + n, err := randNFT(ctx, testData.Rand(), k, from.Address) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + msg := &nft.MsgSend{ + ClassId: n.ClassId, + Id: n.Id, + Sender: from.AddressBech32, + Receiver: to.AddressBech32, + } + + return []simsx.SimAccount{from}, msg + } +} + +// randNFT picks a random NFT from a class belonging to the specified owner(minter). +func randNFT(ctx context.Context, r *simsx.XRand, k keeper.Keeper, minter sdk.AccAddress) (nft.NFT, error) { + c, err := randClass(ctx, r, k) + if err != nil { + return nft.NFT{}, err + } + + if ns := k.GetNFTsOfClassByOwner(ctx, c.Id, minter); len(ns) > 0 { + return ns[r.Intn(len(ns))], nil + } + + n := nft.NFT{ + ClassId: c.Id, + Id: r.StringN(10), + Uri: r.StringN(10), + } + return n, k.Mint(ctx, n, minter) +} + +// randClass picks a random Class. +func randClass(ctx context.Context, r *simsx.XRand, k keeper.Keeper) (nft.Class, error) { + if classes := k.GetClasses(ctx); len(classes) != 0 { + return *classes[r.Intn(len(classes))], nil + } + c := nft.Class{ + Id: r.StringN(10), + Name: r.StringN(10), + Symbol: r.StringN(10), + Description: r.StringN(10), + Uri: r.StringN(10), + } + return c, k.SaveClass(ctx, c) +} diff --git a/x/nft/simulation/operations.go b/x/nft/simulation/operations.go deleted file mode 100644 index f13a47c49e84..000000000000 --- a/x/nft/simulation/operations.go +++ /dev/null @@ -1,170 +0,0 @@ -package simulation - -import ( - "math/rand" - - "cosmossdk.io/x/nft" - "cosmossdk.io/x/nft/keeper" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - cdctypes "github.com/cosmos/cosmos-sdk/codec/types" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -const ( - // OpWeightMsgSend Simulation operation weights constants - OpWeightMsgSend = "op_weight_msg_send" - - // WeightSend nft operations weights - WeightSend = 100 -) - -var TypeMsgSend = sdk.MsgTypeURL(&nft.MsgSend{}) - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - registry cdctypes.InterfaceRegistry, - appParams simtypes.AppParams, - _ codec.JSONCodec, - txCfg client.TxConfig, - ak nft.AccountKeeper, - bk nft.BankKeeper, - k keeper.Keeper, -) simulation.WeightedOperations { - var weightMsgSend int - - appParams.GetOrGenerate(OpWeightMsgSend, &weightMsgSend, nil, - func(_ *rand.Rand) { - weightMsgSend = WeightSend - }, - ) - - return simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgSend, - SimulateMsgSend(codec.NewProtoCodec(registry), txCfg, ak, bk, k), - ), - } -} - -// SimulateMsgSend generates a MsgSend with random values. -func SimulateMsgSend( - _ *codec.ProtoCodec, - txCfg client.TxConfig, - ak nft.AccountKeeper, - bk nft.BankKeeper, - k keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - sender, _ := simtypes.RandomAcc(r, accs) - receiver, _ := simtypes.RandomAcc(r, accs) - - if sender.Address.Equals(receiver.Address) { - return simtypes.NoOpMsg(nft.ModuleName, TypeMsgSend, "sender and receiver are same"), nil, nil - } - - senderAcc := ak.GetAccount(ctx, sender.Address) - spendableCoins := bk.SpendableCoins(ctx, sender.Address) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(nft.ModuleName, TypeMsgSend, err.Error()), nil, err - } - - spendLimit := spendableCoins.Sub(fees...) - if spendLimit == nil { - return simtypes.NoOpMsg(nft.ModuleName, TypeMsgSend, "spend limit is nil"), nil, nil - } - - n, err := randNFT(ctx, r, k, senderAcc.GetAddress()) - if err != nil { - return simtypes.NoOpMsg(nft.ModuleName, TypeMsgSend, err.Error()), nil, err - } - - senderStr, err := ak.AddressCodec().BytesToString(senderAcc.GetAddress().Bytes()) - if err != nil { - return simtypes.NoOpMsg(nft.ModuleName, TypeMsgSend, err.Error()), nil, err - } - - receiverStr, err := ak.AddressCodec().BytesToString(receiver.Address.Bytes()) - if err != nil { - return simtypes.NoOpMsg(nft.ModuleName, TypeMsgSend, err.Error()), nil, err - } - - msg := &nft.MsgSend{ - ClassId: n.ClassId, - Id: n.Id, - Sender: senderStr, - Receiver: receiverStr, - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txCfg, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{senderAcc.GetAccountNumber()}, - []uint64{senderAcc.GetSequence()}, - sender.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(nft.ModuleName, TypeMsgSend, "unable to generate mock tx"), nil, err - } - - if _, _, err = app.SimDeliver(txCfg.TxEncoder(), tx); err != nil { - return simtypes.NoOpMsg(nft.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, nil - } -} - -// randNFT picks a random NFT from a class belonging to the specified owner(minter). -func randNFT(ctx sdk.Context, r *rand.Rand, k keeper.Keeper, minter sdk.AccAddress) (nft.NFT, error) { - c, err := randClass(ctx, r, k) - if err != nil { - return nft.NFT{}, err - } - ns := k.GetNFTsOfClassByOwner(ctx, c.Id, minter) - if len(ns) > 0 { - return ns[r.Intn(len(ns))], nil - } - - n := nft.NFT{ - ClassId: c.Id, - Id: simtypes.RandStringOfLength(r, 10), - Uri: simtypes.RandStringOfLength(r, 10), - } - err = k.Mint(ctx, n, minter) - if err != nil { - return nft.NFT{}, err - } - return n, nil -} - -// randClass picks a random Class. -func randClass(ctx sdk.Context, r *rand.Rand, k keeper.Keeper) (nft.Class, error) { - classes := k.GetClasses(ctx) - if len(classes) == 0 { - c := nft.Class{ - Id: simtypes.RandStringOfLength(r, 10), - Name: simtypes.RandStringOfLength(r, 10), - Symbol: simtypes.RandStringOfLength(r, 10), - Description: simtypes.RandStringOfLength(r, 10), - Uri: simtypes.RandStringOfLength(r, 10), - } - err := k.SaveClass(ctx, c) - if err != nil { - return nft.Class{}, err - } - return c, nil - } - return *classes[r.Intn(len(classes))], nil -} diff --git a/x/params/go.mod b/x/params/go.mod index fcab30fbb022..38463d7ebcec 100644 --- a/x/params/go.mod +++ b/x/params/go.mod @@ -4,7 +4,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 @@ -29,9 +29,7 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/collections v0.4.0 // indirect - cosmossdk.io/schema v0.2.0 // indirect - cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect - cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/x/tx v0.13.3 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect @@ -52,7 +50,6 @@ require ( github.com/cometbft/cometbft v1.0.0-rc1.0.20240908111210-ab0be101882f // indirect github.com/cometbft/cometbft-db v0.15.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect github.com/cosmos/crypto v0.1.2 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect @@ -82,8 +79,6 @@ require ( github.com/google/btree v1.1.3 // indirect github.com/google/flatbuffers v2.0.8+incompatible // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/orderedcode v0.0.1 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/gorilla/handlers v1.5.2 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/websocket v1.5.3 // indirect @@ -94,7 +89,6 @@ require ( github.com/hashicorp/go-metrics v0.5.3 // indirect github.com/hashicorp/go-plugin v1.6.1 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect - github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect @@ -105,12 +99,10 @@ require ( github.com/klauspost/compress v1.17.9 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/lib/pq v1.10.9 // indirect github.com/linxGnu/grocksdb v1.9.3 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/minio/highwayhash v1.0.3 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mtibben/percent v0.2.1 // indirect @@ -121,13 +113,12 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect - github.com/rs/cors v1.11.0 // indirect github.com/rs/zerolog v1.33.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect diff --git a/x/params/go.sum b/x/params/go.sum index a658644fd79f..9fbf0f7bcc62 100644 --- a/x/params/go.sum +++ b/x/params/go.sum @@ -6,8 +6,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,16 +16,14 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0= github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTBqhFkHUrPk= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= @@ -34,12 +32,8 @@ github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/adlio/schema v1.3.6 h1:k1/zc2jNfeiZBA5aFTRy37jlBIuCkXCm0XmvpzCKI9I= -github.com/adlio/schema v1.3.6/go.mod h1:qkxwLgPBd1FgLRHYVCmQT/rrBr3JH38J9LjmVzWNudg= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -60,8 +54,6 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOF github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= -github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -99,8 +91,6 @@ github.com/cometbft/cometbft-db v0.15.0 h1:VLtsRt8udD4jHCyjvrsTBpgz83qne5hnL245A github.com/cometbft/cometbft-db v0.15.0/go.mod h1:EBrFs1GDRiTqrWXYi4v90Awf/gcdD5ExzdPbg4X8+mk= github.com/cometbft/cometbft/api v1.0.0-rc.1 h1:GtdXwDGlqwHYs16A4egjwylfYOMYyEacLBrs3Zvpt7g= github.com/cometbft/cometbft/api v1.0.0-rc.1/go.mod h1:NDFKiBBD8HJC6QQLAoUI99YhsiRZtg2+FJWfk6A6m6o= -github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= -github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= @@ -141,10 +131,6 @@ github.com/dgraph-io/ristretto v0.1.2-0.20240116140435-c67e07994f91 h1:Pux6+xANi github.com/dgraph-io/ristretto v0.1.2-0.20240116140435-c67e07994f91/go.mod h1:swkazRqnUf1N62d0Nutz7KIj2UKqsm/H8tD0nBJAXqM= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY= @@ -320,8 +306,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/linxGnu/grocksdb v1.9.3 h1:s1cbPcOd0cU2SKXRG1nEqCOWYAELQjdqg3RVI2MH9ik= @@ -374,15 +358,7 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.28.1 h1:MijcGUbfYuznzK/5R4CPNoUP/9Xvuo20sXfEm6XxoTA= github.com/onsi/gomega v1.28.1/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= -github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= -github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= -github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= @@ -402,8 +378,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -439,8 +415,6 @@ github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= @@ -592,7 +566,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/x/params/keeper/keeper_test.go b/x/params/keeper/keeper_test.go index d82db839dd35..25b7609fed08 100644 --- a/x/params/keeper/keeper_test.go +++ b/x/params/keeper/keeper_test.go @@ -88,13 +88,11 @@ func TestKeeper(t *testing.T) { // Set params for i, kv := range kvs { - kv := kv require.NotPanics(t, func() { space.Set(ctx, []byte(kv.key), kv.param) }, "space.Set panics, tc #%d", i) } // Test space.Get for i, kv := range kvs { - i, kv := i, kv var param int64 require.NotPanics(t, func() { space.Get(ctx, []byte(kv.key), ¶m) }, "space.Get panics, tc #%d", i) require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) @@ -121,20 +119,17 @@ func TestKeeper(t *testing.T) { // Test invalid space.Get for i, kv := range kvs { - kv := kv var param bool require.Panics(t, func() { space.Get(ctx, []byte(kv.key), ¶m) }, "invalid space.Get not panics, tc #%d", i) } // Test invalid space.Set for i, kv := range kvs { - kv := kv require.Panics(t, func() { space.Set(ctx, []byte(kv.key), true) }, "invalid space.Set not panics, tc #%d", i) } // Test GetSubspace for i, kv := range kvs { - i, kv := i, kv var gparam, param int64 gspace, ok := keeper.GetSubspace("test") require.True(t, ok, "cannot retrieve subspace, tc #%d", i) @@ -219,7 +214,6 @@ func TestSubspace(t *testing.T) { // Test space.Set, space.Modified for i, kv := range kvs { - i, kv := i, kv require.False(t, space.Modified(ctx, []byte(kv.key)), "space.Modified returns true before setting, tc #%d", i) require.NotPanics(t, func() { space.Set(ctx, []byte(kv.key), kv.param) }, "space.Set panics, tc #%d", i) require.True(t, space.Modified(ctx, []byte(kv.key)), "space.Modified returns false after setting, tc #%d", i) @@ -227,7 +221,6 @@ func TestSubspace(t *testing.T) { // Test space.Get, space.GetIfExists for i, kv := range kvs { - i, kv := i, kv require.NotPanics(t, func() { space.GetIfExists(ctx, []byte("invalid"), kv.ptr) }, "space.GetIfExists panics when no value exists, tc #%d", i) require.Equal(t, kv.zero, indirect(kv.ptr), "space.GetIfExists unmarshalls when no value exists, tc #%d", i) require.Panics(t, func() { space.Get(ctx, []byte("invalid"), kv.ptr) }, "invalid space.Get not panics when no value exists, tc #%d", i) diff --git a/x/params/module.go b/x/params/module.go index 006afd56b33c..cc531691e9cc 100644 --- a/x/params/module.go +++ b/x/params/module.go @@ -79,10 +79,5 @@ func (am AppModule) RegisterServices(registrar grpc.ServiceRegistrar) error { // RegisterStoreDecoder doesn't register any type. func (AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {} -// WeightedOperations returns the all the gov module operations with their respective weights. -func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { - return nil -} - // ConsensusVersion implements HasConsensusVersion func (AppModule) ConsensusVersion() uint64 { return ConsensusVersion } diff --git a/x/params/simulation/operations.go b/x/params/simulation/operations.go deleted file mode 100644 index c8e6b7de3f63..000000000000 --- a/x/params/simulation/operations.go +++ /dev/null @@ -1,54 +0,0 @@ -package simulation - -import ( - "fmt" - "math/rand" - - "cosmossdk.io/x/params/types/proposal" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/simulation" -) - -func min(a, b int) int { - if a <= b { - return a - } - return b -} - -// SimulateParamChangeProposalContent returns random parameter change content. -// It will generate a ParameterChangeProposal object with anywhere between 1 and -// the total amount of defined parameters changes, all of which have random valid values. -func SimulateParamChangeProposalContent(paramChangePool []simulation.LegacyParamChange) simulation.ContentSimulatorFn { //nolint:staticcheck // used for legacy testing - numProposals := 0 - // Bound the maximum number of simultaneous parameter changes - maxSimultaneousParamChanges := min(len(paramChangePool), 1000) - if maxSimultaneousParamChanges == 0 { - panic("param changes array is empty") - } - - return func(r *rand.Rand, _ sdk.Context, _ []simulation.Account) simulation.Content { //nolint:staticcheck // used for legacy testing - numChanges := simulation.RandIntBetween(r, 1, maxSimultaneousParamChanges) - paramChanges := make([]proposal.ParamChange, numChanges) - - // perm here takes at most len(paramChangePool) calls to random - paramChoices := r.Perm(len(paramChangePool)) - - for i := 0; i < numChanges; i++ { - spc := paramChangePool[paramChoices[i]] - // add a new distinct parameter to the set of changes - paramChanges[i] = proposal.NewParamChange(spc.Subspace(), spc.Key(), spc.SimValue()(r)) - } - - title := fmt.Sprintf("title from SimulateParamChangeProposalContent-%d", numProposals) - desc := fmt.Sprintf("desc from SimulateParamChangeProposalContent-%d. Random short desc: %s", - numProposals, simulation.RandStringOfLength(r, 20)) - numProposals++ - return proposal.NewParameterChangeProposal( - title, // title - desc, // description - paramChanges, // set of changes - ) - } -} diff --git a/x/params/simulation/operations_test.go b/x/params/simulation/operations_test.go deleted file mode 100644 index 65623381cf4a..000000000000 --- a/x/params/simulation/operations_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package simulation_test - -import ( - "fmt" - "math/rand" - "testing" - - "github.com/stretchr/testify/require" - - "cosmossdk.io/x/params/simulation" - "cosmossdk.io/x/params/types/proposal" - - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" -) - -type MockParamChange struct { - n int -} - -func (pc MockParamChange) Subspace() string { - return fmt.Sprintf("test-Subspace%d", pc.n) -} - -func (pc MockParamChange) Key() string { - return fmt.Sprintf("test-Key%d", pc.n) -} - -func (pc MockParamChange) ComposedKey() string { - return fmt.Sprintf("test-ComposedKey%d", pc.n) -} - -func (pc MockParamChange) SimValue() simtypes.SimValFn { - return func(r *rand.Rand) string { - return fmt.Sprintf("test-value %d%d ", pc.n, int64(simtypes.RandIntBetween(r, 10, 1000))) - } -} - -// make sure that the MockParamChange satisfied the ParamChange interface -var _ simtypes.LegacyParamChange = MockParamChange{} - -func TestSimulateParamChangeProposalContent(t *testing.T) { - s := rand.NewSource(1) - r := rand.New(s) - - ctx := sdk.NewContext(nil, true, nil) - accounts := simtypes.RandomAccounts(r, 3) - paramChangePool := []simtypes.LegacyParamChange{MockParamChange{1}, MockParamChange{2}, MockParamChange{3}} - - // execute operation - op := simulation.SimulateParamChangeProposalContent(paramChangePool) - content := op(r, ctx, accounts) - - require.Equal(t, "desc from SimulateParamChangeProposalContent-0. Random short desc: IivHSlcxgdXhhuTSkuxK", content.GetDescription()) - require.Equal(t, "title from SimulateParamChangeProposalContent-0", content.GetTitle()) - require.Equal(t, "params", content.ProposalRoute()) - require.Equal(t, "ParameterChange", content.ProposalType()) - - pcp, ok := content.(*proposal.ParameterChangeProposal) - require.True(t, ok) - - require.Equal(t, "test-Key2", pcp.Changes[0].GetKey()) - require.Equal(t, "test-value 2791 ", pcp.Changes[0].GetValue()) - require.Equal(t, "test-Subspace2", pcp.Changes[0].GetSubspace()) -} diff --git a/x/params/simulation/proposals.go b/x/params/simulation/proposals.go deleted file mode 100644 index 8dc636fa05c2..000000000000 --- a/x/params/simulation/proposals.go +++ /dev/null @@ -1,25 +0,0 @@ -package simulation - -import ( - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -const ( - // OpWeightSubmitParamChangeProposal app params key for param change proposal - OpWeightSubmitParamChangeProposal = "op_weight_submit_param_change_proposal" - DefaultWeightParamChangeProposal = 5 -) - -// ProposalContents defines the module weighted proposals' contents -// -//nolint:staticcheck // used for legacy testing -func ProposalContents(paramChanges []simtypes.LegacyParamChange) []simtypes.WeightedProposalContent { - return []simtypes.WeightedProposalContent{ - simulation.NewWeightedProposalContent( - OpWeightSubmitParamChangeProposal, - DefaultWeightParamChangeProposal, - SimulateParamChangeProposalContent(paramChanges), - ), - } -} diff --git a/x/params/simulation/proposals_test.go b/x/params/simulation/proposals_test.go deleted file mode 100644 index 63417433492d..000000000000 --- a/x/params/simulation/proposals_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package simulation_test - -import ( - "math/rand" - "testing" - - "github.com/stretchr/testify/require" - - "cosmossdk.io/x/params/simulation" - "cosmossdk.io/x/params/types/proposal" - - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" -) - -func TestProposalContents(t *testing.T) { - // initialize parameters - s := rand.NewSource(1) - r := rand.New(s) - - ctx := sdk.NewContext(nil, true, nil) - accounts := simtypes.RandomAccounts(r, 3) - - paramChangePool := []simtypes.LegacyParamChange{MockParamChange{1}, MockParamChange{2}, MockParamChange{3}} - - // execute ProposalContents function - weightedProposalContent := simulation.ProposalContents(paramChangePool) - require.Len(t, weightedProposalContent, 1) - - w0 := weightedProposalContent[0] - - // tests w0 interface: - require.Equal(t, simulation.OpWeightSubmitParamChangeProposal, w0.AppParamsKey()) - require.Equal(t, simulation.DefaultWeightParamChangeProposal, w0.DefaultWeight()) - - content := w0.ContentSimulatorFn()(r, ctx, accounts) - - require.Equal(t, "desc from SimulateParamChangeProposalContent-0. Random short desc: IivHSlcxgdXhhuTSkuxK", content.GetDescription()) - require.Equal(t, "title from SimulateParamChangeProposalContent-0", content.GetTitle()) - require.Equal(t, "params", content.ProposalRoute()) - require.Equal(t, "ParameterChange", content.ProposalType()) - - pcp, ok := content.(*proposal.ParameterChangeProposal) - require.True(t, ok) - - require.Len(t, pcp.Changes, 1) - require.Equal(t, "test-Key2", pcp.Changes[0].GetKey()) - require.Equal(t, "test-value 2791 ", pcp.Changes[0].GetValue()) - require.Equal(t, "test-Subspace2", pcp.Changes[0].GetSubspace()) -} diff --git a/x/params/types/subspace_test.go b/x/params/types/subspace_test.go index 947c86446bc8..651d868ec18f 100644 --- a/x/params/types/subspace_test.go +++ b/x/params/types/subspace_test.go @@ -236,7 +236,6 @@ func (suite *SubspaceTestSuite) TestSetParamSet() { } for _, tc := range testCases { - tc := tc suite.Run(tc.name, func() { suite.Require().Panics(func() { suite.ss.SetParamSet(suite.ctx, tc.ps) diff --git a/x/protocolpool/depinject.go b/x/protocolpool/depinject.go index ff07c3319639..a2dc1c950c63 100644 --- a/x/protocolpool/depinject.go +++ b/x/protocolpool/depinject.go @@ -10,6 +10,7 @@ import ( "cosmossdk.io/x/protocolpool/types" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simsx" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -79,15 +80,11 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { } -// ProposalMsgs returns all the protocolpool msgs used to simulate governance proposals. -func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { - return simulation.ProposalMsgs() +// ProposalMsgsX returns all the protocolpool msgs used to simulate governance proposals. +func (am AppModule) ProposalMsgsX(weight simsx.WeightSource, reg simsx.Registry) { + reg.Add(weight.Get("msg_community_pool_spend", 50), simulation.MsgCommunityPoolSpendFactory()) } -// WeightedOperations returns the all the protocolpool module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - simState.AppParams, simState.Cdc, simState.TxConfig, - am.accountKeeper, am.bankKeeper, am.keeper, - ) +func (am AppModule) WeightedOperationsX(weight simsx.WeightSource, reg simsx.Registry) { + reg.Add(weight.Get("msg_fund_community_pool", 50), simulation.MsgFundCommunityPoolFactory()) } diff --git a/x/protocolpool/go.mod b/x/protocolpool/go.mod index 75d14c4056d1..24c14115086b 100644 --- a/x/protocolpool/go.mod +++ b/x/protocolpool/go.mod @@ -5,7 +5,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 @@ -21,14 +21,13 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 google.golang.org/grpc v1.66.2 google.golang.org/protobuf v1.34.2 - gotest.tools/v3 v3.5.1 ) require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/log v1.4.1 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -121,7 +120,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -163,6 +162,7 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + gotest.tools/v3 v3.5.1 // indirect pgregory.net/rapid v1.1.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/x/protocolpool/go.sum b/x/protocolpool/go.sum index a658644fd79f..5b3cf3f73e5b 100644 --- a/x/protocolpool/go.sum +++ b/x/protocolpool/go.sum @@ -6,8 +6,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -402,8 +402,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/protocolpool/simulation/msg_factory.go b/x/protocolpool/simulation/msg_factory.go new file mode 100644 index 000000000000..ace70ea2bb81 --- /dev/null +++ b/x/protocolpool/simulation/msg_factory.go @@ -0,0 +1,37 @@ +package simulation + +import ( + "context" + + "cosmossdk.io/x/protocolpool/types" + + "github.com/cosmos/cosmos-sdk/simsx" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func MsgFundCommunityPoolFactory() simsx.SimMsgFactoryFn[*types.MsgFundCommunityPool] { + return func(_ context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgFundCommunityPool) { + funder := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + fundAmount := funder.LiquidBalance().RandSubsetCoins(reporter) + msg := types.NewMsgFundCommunityPool(fundAmount, funder.AddressBech32) + return []simsx.SimAccount{funder}, msg + } +} + +// MsgCommunityPoolSpendFactory creates a gov proposal to send tokens from the community pool to a random account +func MsgCommunityPoolSpendFactory() simsx.SimMsgFactoryFn[*types.MsgCommunityPoolSpend] { + return func(_ context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgCommunityPoolSpend) { + return nil, &types.MsgCommunityPoolSpend{ + Authority: testData.ModuleAccountAddress(reporter, "gov"), + Recipient: testData.AnyAccount(reporter).AddressBech32, + Amount: must(sdk.ParseCoinsNormalized("100stake,2testtoken")), + } + } +} + +func must[T any](r T, err error) T { + if err != nil { + panic(err) + } + return r +} diff --git a/x/protocolpool/simulation/operations.go b/x/protocolpool/simulation/operations.go deleted file mode 100644 index 2118b4488a50..000000000000 --- a/x/protocolpool/simulation/operations.go +++ /dev/null @@ -1,94 +0,0 @@ -package simulation - -import ( - "math/rand" - - "cosmossdk.io/x/protocolpool/keeper" - "cosmossdk.io/x/protocolpool/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - OpWeightMsgFundCommunityPool = "op_weight_msg_fund_community_pool" - - DefaultWeightMsgFundCommunityPool int = 50 -) - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - appParams simtypes.AppParams, - _ codec.JSONCodec, - txConfig client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k keeper.Keeper, -) simulation.WeightedOperations { - var weightMsgFundCommunityPool int - appParams.GetOrGenerate(OpWeightMsgFundCommunityPool, &weightMsgFundCommunityPool, nil, func(_ *rand.Rand) { - weightMsgFundCommunityPool = DefaultWeightMsgFundCommunityPool - }) - - return simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgFundCommunityPool, - SimulateMsgFundCommunityPool(txConfig, ak, bk, k), - ), - } -} - -// SimulateMsgFundCommunityPool simulates MsgFundCommunityPool execution where -// a random account sends a random amount of its funds to the community pool. -func SimulateMsgFundCommunityPool(txConfig client.TxConfig, ak types.AccountKeeper, bk types.BankKeeper, _ keeper.Keeper) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - funder, _ := simtypes.RandomAcc(r, accs) - - account := ak.GetAccount(ctx, funder.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - fundAmount := simtypes.RandSubsetCoins(r, spendable) - if fundAmount.Empty() { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgFundCommunityPool{}), "fund amount is empty"), nil, nil - } - - var ( - fees sdk.Coins - err error - ) - - coins, hasNeg := spendable.SafeSub(fundAmount...) - if !hasNeg { - fees, err = simtypes.RandomFees(r, coins) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgFundCommunityPool{}), "unable to generate fees"), nil, err - } - } - - funderAddr, err := ak.AddressCodec().BytesToString(funder.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgFundCommunityPool{}), "unable to get funder address"), nil, err - } - msg := types.NewMsgFundCommunityPool(fundAmount, funderAddr) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txConfig, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: funder, - AccountKeeper: ak, - ModuleName: types.ModuleName, - } - - return simulation.GenAndDeliverTx(txCtx, fees) - } -} diff --git a/x/protocolpool/simulation/proposals.go b/x/protocolpool/simulation/proposals.go deleted file mode 100644 index 0afddda38f01..000000000000 --- a/x/protocolpool/simulation/proposals.go +++ /dev/null @@ -1,57 +0,0 @@ -package simulation - -import ( - "context" - "math/rand" - - coreaddress "cosmossdk.io/core/address" - pooltypes "cosmossdk.io/x/protocolpool/types" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -const ( - OpWeightMsgCommunityPoolSpend = "op_weight_msg_community_pool_spend" - - DefaultWeightMsgCommunityPoolSpend int = 50 -) - -func ProposalMsgs() []simtypes.WeightedProposalMsg { - return []simtypes.WeightedProposalMsg{ - simulation.NewWeightedProposalMsgX( - OpWeightMsgCommunityPoolSpend, - DefaultWeightMsgCommunityPoolSpend, - SimulateMsgCommunityPoolSpend, - ), - } -} - -func SimulateMsgCommunityPoolSpend(_ context.Context, r *rand.Rand, _ []simtypes.Account, cdc coreaddress.Codec) (sdk.Msg, error) { - // use the default gov module account address as authority - var authority sdk.AccAddress = address.Module("gov") - - accs := simtypes.RandomAccounts(r, 5) - acc, _ := simtypes.RandomAcc(r, accs) - - coins, err := sdk.ParseCoinsNormalized("100stake,2testtoken") - if err != nil { - return nil, err - } - - authorityAddr, err := cdc.BytesToString(authority) - if err != nil { - return nil, err - } - recipentAddr, err := cdc.BytesToString(acc.Address) - if err != nil { - return nil, err - } - return &pooltypes.MsgCommunityPoolSpend{ - Authority: authorityAddr, - Recipient: recipentAddr, - Amount: coins, - }, nil -} diff --git a/x/protocolpool/simulation/proposals_test.go b/x/protocolpool/simulation/proposals_test.go deleted file mode 100644 index b452b01970fc..000000000000 --- a/x/protocolpool/simulation/proposals_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package simulation_test - -import ( - "context" - "math/rand" - "testing" - - "gotest.tools/v3/assert" - - "cosmossdk.io/x/protocolpool/simulation" - pooltypes "cosmossdk.io/x/protocolpool/types" - - codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" -) - -func TestProposalMsgs(t *testing.T) { - // initialize parameters - s := rand.NewSource(1) - r := rand.New(s) - addressCodec := codectestutil.CodecOptions{}.GetAddressCodec() - accounts := simtypes.RandomAccounts(r, 3) - - // execute ProposalMsgs function - weightedProposalMsgs := simulation.ProposalMsgs() - assert.Assert(t, len(weightedProposalMsgs) == 1) - - w0 := weightedProposalMsgs[0] - - // tests w0 interface: - assert.Equal(t, simulation.OpWeightMsgCommunityPoolSpend, w0.AppParamsKey()) - assert.Equal(t, simulation.DefaultWeightMsgCommunityPoolSpend, w0.DefaultWeight()) - - msg, err := w0.MsgSimulatorFn()(context.Background(), r, accounts, addressCodec) - assert.NilError(t, err) - msgCommunityPoolSpend, ok := msg.(*pooltypes.MsgCommunityPoolSpend) - assert.Assert(t, ok) - - coins, err := sdk.ParseCoinsNormalized("100stake,2testtoken") - assert.NilError(t, err) - - authAddr, err := addressCodec.BytesToString(address.Module("gov")) - assert.NilError(t, err) - assert.Equal(t, authAddr, msgCommunityPoolSpend.Authority) - assert.Assert(t, msgCommunityPoolSpend.Amount.Equal(coins)) -} diff --git a/x/simulation/client/cli/flags.go b/x/simulation/client/cli/flags.go index 311ce7017d85..1dc05fa47f29 100644 --- a/x/simulation/client/cli/flags.go +++ b/x/simulation/client/cli/flags.go @@ -30,6 +30,7 @@ var ( FlagPeriodValue uint FlagGenesisTimeValue int64 FlagSigverifyTxValue bool + FlagFauxMerkle bool ) // GetSimulatorFlags gets the values of all the available simulation flags @@ -54,6 +55,7 @@ func GetSimulatorFlags() { flag.UintVar(&FlagPeriodValue, "Period", 0, "run slow invariants only once every period assertions") flag.Int64Var(&FlagGenesisTimeValue, "GenesisTime", time.Now().Unix(), "use current time as genesis UNIX time for default") flag.BoolVar(&FlagSigverifyTxValue, "SigverifyTx", true, "whether to sigverify check for transaction ") + flag.BoolVar(&FlagFauxMerkle, "FauxMerkle", false, "use faux merkle instead of iavl") } // NewConfigFromFlags creates a simulation from the retrieved values of the flags. @@ -73,5 +75,6 @@ func NewConfigFromFlags() simulation.Config { Lean: FlagLeanValue, Commit: FlagCommitValue, DBBackend: FlagDBBackendValue, + FauxMerkle: FlagFauxMerkle, } } diff --git a/x/simulation/log.go b/x/simulation/log.go index c1f9c439e10b..4547e8f96d05 100644 --- a/x/simulation/log.go +++ b/x/simulation/log.go @@ -76,7 +76,7 @@ func createLogFile(seed int64) *os.File { if err != nil { panic(err) } - fmt.Printf("Logs to writing to %s\n", filePath) + fmt.Printf("Logs to writing to %q\n", filePath) return f } diff --git a/x/simulation/mock_cometbft.go b/x/simulation/mock_cometbft.go index 0dbfaec4654d..c9572dd46924 100644 --- a/x/simulation/mock_cometbft.go +++ b/x/simulation/mock_cometbft.go @@ -92,9 +92,9 @@ func updateValidators( if update.Power == 0 { if _, ok := current[str]; !ok { - tb.Fatalf("tried to delete a nonexistent validator: %s", str) + tb.Logf("tried to delete a nonexistent validator: %s", str) + continue } - event("end_block", "validator_updates", "kicked") delete(current, str) } else if _, ok := current[str]; ok { @@ -187,15 +187,17 @@ func RandomRequestFinalizeBlock( params.evidenceFraction = 0.9 } + totalBlocksProcessed := len(pastTimes) + startHeight := blockHeight - int64(totalBlocksProcessed) + 1 for r.Float64() < params.EvidenceFraction() { vals := voteInfos height := blockHeight misbehaviorTime := time - if r.Float64() < params.PastEvidenceFraction() && height > 1 { - height = int64(r.Intn(int(height)-1)) + 1 // CometBFT starts at height 1 - // array indices offset by one - misbehaviorTime = pastTimes[height-1] - vals = pastVoteInfos[height-1] + if r.Float64() < params.PastEvidenceFraction() && totalBlocksProcessed > 1 { + n := int64(r.Intn(totalBlocksProcessed)) + misbehaviorTime = pastTimes[n] + vals = pastVoteInfos[n] + height = startHeight + n } validator := vals[r.Intn(len(vals))].Validator diff --git a/x/simulation/operation.go b/x/simulation/operation.go index 8146ef15273a..6ba092713f94 100644 --- a/x/simulation/operation.go +++ b/x/simulation/operation.go @@ -76,13 +76,12 @@ func NewOperationQueue() OperationQueue { } // queueOperations adds all future operations into the operation queue. -func queueOperations(queuedOps OperationQueue, queuedTimeOps, futureOps []simulation.FutureOperation) { +func queueOperations(queuedOps OperationQueue, queuedTimeOps *[]simulation.FutureOperation, futureOps []simulation.FutureOperation) { if futureOps == nil { return } for _, futureOp := range futureOps { - futureOp := futureOp if futureOp.BlockHeight != 0 { if val, ok := queuedOps[futureOp.BlockHeight]; ok { queuedOps[futureOp.BlockHeight] = append(val, futureOp.Op) @@ -96,15 +95,15 @@ func queueOperations(queuedOps OperationQueue, queuedTimeOps, futureOps []simula // TODO: Replace with proper sorted data structure, so don't have the // copy entire slice index := sort.Search( - len(queuedTimeOps), + len(*queuedTimeOps), func(i int) bool { - return queuedTimeOps[i].BlockTime.After(futureOp.BlockTime) + return (*queuedTimeOps)[i].BlockTime.After(futureOp.BlockTime) }, ) - queuedTimeOps = append(queuedTimeOps, simulation.FutureOperation{}) - copy(queuedTimeOps[index+1:], queuedTimeOps[index:]) - queuedTimeOps[index] = futureOp + *queuedTimeOps = append(*queuedTimeOps, simulation.FutureOperation{}) + copy((*queuedTimeOps)[index+1:], (*queuedTimeOps)[index:]) + (*queuedTimeOps)[index] = futureOp } } diff --git a/x/simulation/params.go b/x/simulation/params.go index 4fce44cff82e..1c6032c867c1 100644 --- a/x/simulation/params.go +++ b/x/simulation/params.go @@ -185,8 +185,8 @@ func (w WeightedProposalContent) ContentSimulatorFn() simulation.ContentSimulato // Consensus Params -// randomConsensusParams returns random simulation consensus parameters, it extracts the Evidence from the Staking genesis state. -func randomConsensusParams(r *rand.Rand, appState json.RawMessage, cdc codec.JSONCodec, maxGas int64) *cmtproto.ConsensusParams { +// RandomConsensusParams returns random simulation consensus parameters, it extracts the Evidence from the Staking genesis state. +func RandomConsensusParams(r *rand.Rand, appState json.RawMessage, cdc codec.JSONCodec, maxGas int64) *cmtproto.ConsensusParams { var genesisState map[string]json.RawMessage err := json.Unmarshal(appState, &genesisState) if err != nil { diff --git a/x/simulation/params_test.go b/x/simulation/params_test.go index e4d6f380d101..1e05e3adadc8 100644 --- a/x/simulation/params_test.go +++ b/x/simulation/params_test.go @@ -1,6 +1,7 @@ package simulation import ( + "context" "fmt" "math/rand" "testing" @@ -29,7 +30,7 @@ func TestNewWeightedProposalContent(t *testing.T) { key := "theKey" weight := 1 content := &testContent{} - f := func(r *rand.Rand, ctx sdk.Context, accs []simtypes.Account) simtypes.Content { //nolint:staticcheck // used for legacy testing + f := func(r *rand.Rand, ctx context.Context, accs []simtypes.Account) simtypes.Content { //nolint:staticcheck // used for legacy testing return content } diff --git a/x/simulation/simulate.go b/x/simulation/simulate.go index cd4fbe590799..faf69e1df4db 100644 --- a/x/simulation/simulate.go +++ b/x/simulation/simulate.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "math/rand" + "slices" "testing" "time" @@ -21,7 +22,7 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/simulation" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) const AverageBlockTime = 6 * time.Second @@ -30,23 +31,24 @@ const AverageBlockTime = 6 * time.Second func initChain( r *rand.Rand, params Params, - accounts []simulation.Account, + accounts []simtypes.Account, app *baseapp.BaseApp, - appStateFn simulation.AppStateFn, - config simulation.Config, + appStateFn simtypes.AppStateFn, + config simtypes.Config, cdc codec.JSONCodec, -) (mockValidators, time.Time, []simulation.Account, string) { +) (mockValidators, time.Time, []simtypes.Account, string) { blockMaxGas := int64(-1) if config.BlockMaxGas > 0 { blockMaxGas = config.BlockMaxGas } appState, accounts, chainID, genesisTimestamp := appStateFn(r, accounts, config) - consensusParams := randomConsensusParams(r, appState, cdc, blockMaxGas) + consensusParams := RandomConsensusParams(r, appState, cdc, blockMaxGas) req := abci.InitChainRequest{ AppStateBytes: appState, ChainId: chainID, ConsensusParams: consensusParams, Time: genesisTimestamp, + InitialHeight: int64(config.InitialBlockHeight), } res, err := app.InitChain(&req) if err != nil { @@ -59,22 +61,22 @@ func initChain( // SimulateFromSeed tests an application by running the provided // operations, testing the provided invariants, but using the provided config.Seed. -func SimulateFromSeed( // exists for backwards compatibility only +func SimulateFromSeed( tb testing.TB, logger corelog.Logger, w io.Writer, app *baseapp.BaseApp, - appStateFn simulation.AppStateFn, - randAccFn simulation.RandomAccountFn, + appStateFn simtypes.AppStateFn, + randAccFn simtypes.RandomAccountFn, ops WeightedOperations, blockedAddrs map[string]bool, - config simulation.Config, + config simtypes.Config, cdc codec.JSONCodec, addressCodec address.Codec, -) (exportedParams Params, err error) { +) (exportedParams Params, accs []simtypes.Account, err error) { tb.Helper() mode, _, _ := getTestingMode(tb) - return SimulateFromSeedX(tb, logger, w, app, appStateFn, randAccFn, ops, blockedAddrs, config, cdc, addressCodec, NewLogWriter(mode)) + return SimulateFromSeedX(tb, logger, w, app, appStateFn, randAccFn, ops, blockedAddrs, config, cdc, NewLogWriter(mode)) } // SimulateFromSeedX tests an application by running the provided @@ -84,16 +86,20 @@ func SimulateFromSeedX( logger corelog.Logger, w io.Writer, app *baseapp.BaseApp, - appStateFn simulation.AppStateFn, - randAccFn simulation.RandomAccountFn, + appStateFn simtypes.AppStateFn, + randAccFn simtypes.RandomAccountFn, ops WeightedOperations, blockedAddrs map[string]bool, - config simulation.Config, + config simtypes.Config, cdc codec.JSONCodec, - addressCodec address.Codec, logWriter LogWriter, -) (exportedParams Params, err error) { +) (exportedParams Params, accs []simtypes.Account, err error) { tb.Helper() + defer func() { + if err != nil { + logWriter.PrintLogs() + } + }() // in case we have to end early, don't os.Exit so that we can run cleanup code. testingMode, _, b := getTestingMode(tb) @@ -105,7 +111,7 @@ func SimulateFromSeedX( logger.Debug("Randomized simulation setup", "params", mustMarshalJSONIndent(params)) timeDiff := maxTimePerBlock - minTimePerBlock - accs := randAccFn(r, params.NumKeys()) + accs = randAccFn(r, params.NumKeys()) eventStats := NewEventStats() // Second variable to keep pending validator set (delayed one block since @@ -114,31 +120,21 @@ func SimulateFromSeedX( // At least 2 accounts must be added here, otherwise when executing SimulateMsgSend // two accounts will be selected to meet the conditions from != to and it will fall into an infinite loop. if len(accs) <= 1 { - return params, errors.New("at least two genesis accounts are required") + return params, accs, errors.New("at least two genesis accounts are required") } config.ChainID = chainID // remove module account address if they exist in accs - var tmpAccs []simulation.Account - - for _, acc := range accs { - accAddr, err := addressCodec.BytesToString(acc.Address) - if err != nil { - return params, err - } - if !blockedAddrs[accAddr] { - tmpAccs = append(tmpAccs, acc) - } - } - - accs = tmpAccs + accs = slices.DeleteFunc(accs, func(acc simtypes.Account) bool { + return blockedAddrs[acc.AddressBech32] + }) nextValidators := validators var ( pastTimes []time.Time pastVoteInfos [][]abci.VoteInfo - timeOperationQueue []simulation.FutureOperation + timeOperationQueue []simtypes.FutureOperation blockHeight = int64(config.InitialBlockHeight) proposerAddress = validators.randomProposer(r) @@ -168,7 +164,7 @@ func SimulateFromSeedX( eventStats.Tally, ops, operationQueue, - timeOperationQueue, + &timeOperationQueue, logWriter, config, ) @@ -191,6 +187,10 @@ func SimulateFromSeedX( exportedParams = params } + if _, err := app.FinalizeBlock(finalizeBlockReq); err != nil { + return params, accs, fmt.Errorf("block finalization failed at height %d: %+w", blockHeight, err) + } + for blockHeight < int64(config.NumBlocks+config.InitialBlockHeight) { pastTimes = append(pastTimes, blockTime) pastVoteInfos = append(pastVoteInfos, finalizeBlockReq.DecidedLastCommit.Votes) @@ -200,7 +200,7 @@ func SimulateFromSeedX( res, err := app.FinalizeBlock(finalizeBlockReq) if err != nil { - return params, fmt.Errorf("block finalization failed at height %d: %w", blockHeight, err) + return params, accs, fmt.Errorf("block finalization failed at height %d: %w", blockHeight, err) } ctx := app.NewContextLegacy(false, cmtproto.Header{ @@ -219,15 +219,14 @@ func SimulateFromSeedX( tb, operationQueue, blockTime, int(blockHeight), r, app, ctx, accs, logWriter, eventStats.Tally, config.Lean, config.ChainID, ) - numQueuedTimeOpsRan, timeFutureOps := runQueuedTimeOperations(tb, - timeOperationQueue, int(blockHeight), blockTime, + &timeOperationQueue, int(blockHeight), blockTime, r, app, ctx, accs, logWriter, eventStats.Tally, config.Lean, config.ChainID, ) futureOps = append(futureOps, timeFutureOps...) - queueOperations(operationQueue, timeOperationQueue, futureOps) + queueOperations(operationQueue, &timeOperationQueue, futureOps) // run standard operations operations := blockSimulator(r, app, ctx, accs, cmtproto.Header{ @@ -237,7 +236,6 @@ func SimulateFromSeedX( ChainID: config.ChainID, }) opCount += operations + numQueuedOpsRan + numQueuedTimeOpsRan - blockHeight++ logWriter.AddEntry(EndBlockEntry(blockTime, blockHeight)) @@ -249,7 +247,7 @@ func SimulateFromSeedX( if config.Commit { app.SimWriteState() if _, err := app.Commit(); err != nil { - return params, fmt.Errorf("commit failed at height %d: %w", blockHeight, err) + return params, accs, fmt.Errorf("commit failed at height %d: %w", blockHeight, err) } } @@ -272,7 +270,6 @@ func SimulateFromSeedX( exportedParams = params } } - logger.Info("Simulation complete", "height", blockHeight, "block-time", blockTime, "opsCount", opCount, "run-time", time.Since(startTime), "app-hash", hex.EncodeToString(app.LastCommitID().Hash)) @@ -282,14 +279,14 @@ func SimulateFromSeedX( } else { eventStats.Print(w) } - return exportedParams, err + return exportedParams, accs, err } type blockSimFn func( r *rand.Rand, - app *baseapp.BaseApp, + app simtypes.AppEntrypoint, ctx sdk.Context, - accounts []simulation.Account, + accounts []simtypes.Account, header cmtproto.Header, ) (opCount int) @@ -297,8 +294,8 @@ type blockSimFn func( // parameters being passed every time, to minimize memory overhead. func createBlockSimulator(tb testing.TB, printProgress bool, w io.Writer, params Params, event func(route, op, evResult string), ops WeightedOperations, - operationQueue OperationQueue, timeOperationQueue []simulation.FutureOperation, - logWriter LogWriter, config simulation.Config, + operationQueue OperationQueue, timeOperationQueue *[]simtypes.FutureOperation, + logWriter LogWriter, config simtypes.Config, ) blockSimFn { tb.Helper() lastBlockSizeState := 0 // state for [4 * uniform distribution] @@ -306,7 +303,7 @@ func createBlockSimulator(tb testing.TB, printProgress bool, w io.Writer, params selectOp := ops.getSelectOpFn() return func( - r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accounts []simulation.Account, header cmtproto.Header, + r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accounts []simtypes.Account, header cmtproto.Header, ) (opCount int) { _, _ = fmt.Fprintf( w, "\rSimulating... block %d/%d, operation %d/%d.", @@ -315,7 +312,7 @@ func createBlockSimulator(tb testing.TB, printProgress bool, w io.Writer, params lastBlockSizeState, blocksize = getBlockSize(r, params, lastBlockSizeState, config.BlockSize) type opAndR struct { - op simulation.Operation + op simtypes.Operation rand *rand.Rand } @@ -363,11 +360,11 @@ Comment: %s`, } } -func runQueuedOperations(tb testing.TB, queueOps map[int][]simulation.Operation, +func runQueuedOperations(tb testing.TB, queueOps map[int][]simtypes.Operation, blockTime time.Time, height int, r *rand.Rand, app *baseapp.BaseApp, - ctx sdk.Context, accounts []simulation.Account, logWriter LogWriter, + ctx sdk.Context, accounts []simtypes.Account, logWriter LogWriter, event func(route, op, evResult string), lean bool, chainID string, -) (numOpsRan int, allFutureOps []simulation.FutureOperation) { +) (numOpsRan int, allFutureOps []simtypes.FutureOperation) { tb.Helper() queuedOp, ok := queueOps[height] if !ok { @@ -375,11 +372,15 @@ func runQueuedOperations(tb testing.TB, queueOps map[int][]simulation.Operation, } // Keep all future operations - allFutureOps = make([]simulation.FutureOperation, 0) + allFutureOps = make([]simtypes.FutureOperation, 0) numOpsRan = len(queuedOp) for i := 0; i < numOpsRan; i++ { opMsg, futureOps, err := queuedOp[i](r, app, ctx, accounts, chainID) + if err != nil { + logWriter.PrintLogs() + tb.FailNow() + } if len(futureOps) > 0 { allFutureOps = append(allFutureOps, futureOps...) } @@ -387,49 +388,44 @@ func runQueuedOperations(tb testing.TB, queueOps map[int][]simulation.Operation, opMsg.LogEvent(event) if !lean || opMsg.OK { - logWriter.AddEntry((QueuedMsgEntry(blockTime, int64(height), opMsg))) + logWriter.AddEntry(QueuedMsgEntry(blockTime, int64(height), opMsg)) } - if err != nil { - logWriter.PrintLogs() - tb.FailNow() - } } delete(queueOps, height) return numOpsRan, allFutureOps } -func runQueuedTimeOperations(tb testing.TB, queueOps []simulation.FutureOperation, +func runQueuedTimeOperations(tb testing.TB, queueOps *[]simtypes.FutureOperation, height int, currentTime time.Time, r *rand.Rand, - app *baseapp.BaseApp, ctx sdk.Context, accounts []simulation.Account, + app *baseapp.BaseApp, ctx sdk.Context, accounts []simtypes.Account, logWriter LogWriter, event func(route, op, evResult string), lean bool, chainID string, -) (numOpsRan int, allFutureOps []simulation.FutureOperation) { +) (numOpsRan int, allFutureOps []simtypes.FutureOperation) { tb.Helper() // Keep all future operations - allFutureOps = make([]simulation.FutureOperation, 0) - numOpsRan = 0 - for len(queueOps) > 0 && currentTime.After(queueOps[0].BlockTime) { - opMsg, futureOps, err := queueOps[0].Op(r, app, ctx, accounts, chainID) + for len(*queueOps) > 0 && currentTime.After((*queueOps)[0].BlockTime) { + if qOp := (*queueOps)[0]; qOp.Op != nil { + opMsg, futureOps, err := qOp.Op(r, app, ctx, accounts, chainID) - opMsg.LogEvent(event) + opMsg.LogEvent(event) - if !lean || opMsg.OK { - logWriter.AddEntry(QueuedMsgEntry(currentTime, int64(height), opMsg)) - } + if !lean || opMsg.OK { + logWriter.AddEntry(QueuedMsgEntry(currentTime, int64(height), opMsg)) + } - if err != nil { - logWriter.PrintLogs() - tb.FailNow() - } + if err != nil { + logWriter.PrintLogs() + tb.Fatal(err) + } - if len(futureOps) > 0 { - allFutureOps = append(allFutureOps, futureOps...) + if len(futureOps) > 0 { + allFutureOps = append(allFutureOps, futureOps...) + } } - - queueOps = queueOps[1:] + *queueOps = slices.Delete(*queueOps, 0, 1) numOpsRan++ } diff --git a/x/simulation/simulate_test.go b/x/simulation/simulate_test.go new file mode 100644 index 000000000000..31fe943acfa0 --- /dev/null +++ b/x/simulation/simulate_test.go @@ -0,0 +1,57 @@ +package simulation + +import ( + "math/rand" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +func TestRunQueuedTimeOperations(t *testing.T) { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + ctx := sdk.Context{} + lw := NewLogWriter(true) + noopEvent := func(route, op, evResult string) {} + var acc []simtypes.Account + noOp := simtypes.FutureOperation{ + Op: func(gotR *rand.Rand, gotApp simtypes.AppEntrypoint, ctx sdk.Context, accounts []simtypes.Account, chainID string) (OperationMsg simtypes.OperationMsg, futureOps []simtypes.FutureOperation, err error) { + return simtypes.OperationMsg{}, nil, nil + }, + } + futureOp := simtypes.FutureOperation{ + Op: func(gotR *rand.Rand, gotApp simtypes.AppEntrypoint, ctx sdk.Context, accounts []simtypes.Account, chainID string) (OperationMsg simtypes.OperationMsg, futureOps []simtypes.FutureOperation, err error) { + return simtypes.OperationMsg{}, []simtypes.FutureOperation{noOp}, nil + }, + } + + specs := map[string]struct { + queueOps []simtypes.FutureOperation + expOps []simtypes.FutureOperation + }{ + "empty": {}, + "single": { + queueOps: []simtypes.FutureOperation{noOp}, + }, + "multi": { + queueOps: []simtypes.FutureOperation{noOp, noOp}, + }, + "future op": { + queueOps: []simtypes.FutureOperation{futureOp}, + expOps: []simtypes.FutureOperation{noOp}, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + expOps := len(spec.queueOps) + n, fOps := runQueuedTimeOperations(t, &spec.queueOps, 0, time.Now(), r, nil, ctx, acc, lw, noopEvent, false, "testing") + require.Equal(t, expOps, n) + assert.Empty(t, spec.queueOps) + assert.Len(t, fOps, len(spec.expOps)) // using len as equal fails with Go 1.23 now + }) + } +} diff --git a/x/slashing/go.mod b/x/slashing/go.mod index 9c0050d83d28..562e127b7831 100644 --- a/x/slashing/go.mod +++ b/x/slashing/go.mod @@ -5,7 +5,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 @@ -30,7 +30,7 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/log v1.4.1 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/tx v0.13.3 // indirect filippo.io/edwards25519 v1.1.0 // indirect @@ -122,7 +122,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/x/slashing/go.sum b/x/slashing/go.sum index 03e82f35386e..796186d54957 100644 --- a/x/slashing/go.sum +++ b/x/slashing/go.sum @@ -6,8 +6,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -404,8 +404,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/slashing/keeper/msg_server_test.go b/x/slashing/keeper/msg_server_test.go index 39b04636328d..2554ac5fe2ab 100644 --- a/x/slashing/keeper/msg_server_test.go +++ b/x/slashing/keeper/msg_server_test.go @@ -135,7 +135,6 @@ func (s *KeeperTestSuite) TestUpdateParams() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { _, err := s.msgServer.UpdateParams(s.ctx, tc.request) if tc.expectErr { @@ -345,7 +344,6 @@ func (s *KeeperTestSuite) TestUnjail() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { req := tc.malleate() _, err := s.msgServer.Unjail(s.ctx, req) diff --git a/x/slashing/module.go b/x/slashing/module.go index e210daf33af8..8fbd57939533 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -18,6 +18,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/simsx" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) @@ -40,12 +41,9 @@ var ( // AppModule implements an application module for the slashing module. type AppModule struct { cdc codec.Codec - registry cdctypes.InterfaceRegistry cometService comet.Service keeper keeper.Keeper - accountKeeper types.AccountKeeper - bankKeeper types.BankKeeper stakingKeeper types.StakingKeeper } @@ -61,10 +59,7 @@ func NewAppModule( ) AppModule { return AppModule{ cdc: cdc, - registry: registry, keeper: keeper, - accountKeeper: ak, - bankKeeper: bk, stakingKeeper: sk, cometService: cs, } @@ -171,9 +166,9 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { simulation.RandomizedGenState(simState) } -// ProposalMsgs returns msgs used for governance proposals for simulations. -func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { - return simulation.ProposalMsgs() +// ProposalMsgsX returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_update_params", 100), simulation.MsgUpdateParamsFactory()) } // RegisterStoreDecoder registers a decoder for slashing module's types @@ -181,10 +176,8 @@ func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) } -// WeightedOperations returns the all the slashing module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - am.registry, simState.AppParams, simState.Cdc, simState.TxConfig, - am.accountKeeper, am.bankKeeper, am.keeper, am.stakingKeeper, - ) +// WeightedOperationsX returns the all the slashing module operations with their respective weights. +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + // note: using old keys for backwards compatibility + reg.Add(weights.Get("msg_unjail", 20), simulation.MsgUnjailFactory(am.keeper, am.stakingKeeper)) } diff --git a/x/slashing/simulation/decoder_test.go b/x/slashing/simulation/decoder_test.go index 50d9887a491d..6a668a8ddfe7 100644 --- a/x/slashing/simulation/decoder_test.go +++ b/x/slashing/simulation/decoder_test.go @@ -50,7 +50,6 @@ func TestDecodeStore(t *testing.T) { {"other", "", true}, } for i, tt := range tests { - i, tt := i, tt t.Run(tt.name, func(t *testing.T) { if tt.panics { require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) diff --git a/x/slashing/simulation/genesis.go b/x/slashing/simulation/genesis.go index 26ea1aeb4072..8316b06a7c20 100644 --- a/x/slashing/simulation/genesis.go +++ b/x/slashing/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" "time" @@ -71,10 +69,5 @@ func RandomizedGenState(simState *module.SimulationState) { slashingGenesis := types.NewGenesisState(params, []types.SigningInfo{}, []types.ValidatorMissedBlocks{}) - bz, err := json.MarshalIndent(&slashingGenesis, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated slashing parameters:\n%s\n", bz) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(slashingGenesis) } diff --git a/x/slashing/simulation/msg_factory.go b/x/slashing/simulation/msg_factory.go new file mode 100644 index 000000000000..86a59544425c --- /dev/null +++ b/x/slashing/simulation/msg_factory.go @@ -0,0 +1,98 @@ +package simulation + +import ( + "context" + "errors" + "time" + + sdkmath "cosmossdk.io/math" + "cosmossdk.io/x/slashing/keeper" + "cosmossdk.io/x/slashing/types" + + "github.com/cosmos/cosmos-sdk/simsx" +) + +func MsgUnjailFactory(k keeper.Keeper, sk types.StakingKeeper) simsx.SimMsgFactoryX { + return simsx.NewSimMsgFactoryWithDeliveryResultHandler[*types.MsgUnjail](func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgUnjail, simsx.SimDeliveryResultHandler) { + allVals, err := sk.GetAllValidators(ctx) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil, nil + } + validator := simsx.OneOf(testData.Rand(), allVals) + if !validator.IsJailed() { + reporter.Skip("validator not jailed") + return nil, nil, nil + } + if validator.InvalidExRate() { + reporter.Skip("validator with invalid exchange rate") + return nil, nil, nil + } + + info, err := k.ValidatorSigningInfo.Get(ctx, must(validator.GetConsAddr())) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil, nil + } + valOperBz := must(sk.ValidatorAddressCodec().StringToBytes(validator.GetOperator())) + valOper := testData.GetAccountbyAccAddr(reporter, valOperBz) + if reporter.IsSkipped() { + return nil, nil, nil + } + + selfDel, err := sk.Delegation(ctx, valOper.Address, valOperBz) + if selfDel == nil || err != nil { + reporter.Skip("no self delegation") + return nil, nil, nil + } + var handler simsx.SimDeliveryResultHandler + // result should fail if: + // - validator cannot be unjailed due to tombstone + // - validator is still in jailed period + // - self delegation too low + if info.Tombstoned || + simsx.BlockTime(ctx).Before(info.JailedUntil) || + selfDel.GetShares().IsNil() || + validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) { + handler = func(err error) error { + if err == nil { + switch { + case info.Tombstoned: + return errors.New("validator should not have been unjailed if validator tombstoned") + case simsx.BlockTime(ctx).Before(info.JailedUntil): + return errors.New("validator unjailed while validator still in jail period") + case selfDel.GetShares().IsNil() || validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()): + return errors.New("validator unjailed even though self-delegation too low") + } + } + return nil + } + } + return []simsx.SimAccount{valOper}, types.NewMsgUnjail(validator.GetOperator()), handler + }) +} + +// MsgUpdateParamsFactory creates a gov proposal for param updates +func MsgUpdateParamsFactory() simsx.SimMsgFactoryFn[*types.MsgUpdateParams] { + return func(_ context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgUpdateParams) { + r := testData.Rand() + params := types.DefaultParams() + params.DowntimeJailDuration = time.Duration(r.Timestamp().UnixNano()) + params.SignedBlocksWindow = int64(r.IntInRange(1, 1000)) + params.MinSignedPerWindow = sdkmath.LegacyNewDecWithPrec(int64(r.IntInRange(1, 100)), 2) + params.SlashFractionDoubleSign = sdkmath.LegacyNewDecWithPrec(int64(r.IntInRange(1, 100)), 2) + params.SlashFractionDowntime = sdkmath.LegacyNewDecWithPrec(int64(r.IntInRange(1, 100)), 2) + + return nil, &types.MsgUpdateParams{ + Authority: testData.ModuleAccountAddress(reporter, "gov"), + Params: params, + } + } +} + +func must[T any](r T, err error) T { + if err != nil { + panic(err) + } + return r +} diff --git a/x/slashing/simulation/operations.go b/x/slashing/simulation/operations.go deleted file mode 100644 index e14cef141346..000000000000 --- a/x/slashing/simulation/operations.go +++ /dev/null @@ -1,159 +0,0 @@ -package simulation - -import ( - "errors" - "math/rand" - - "cosmossdk.io/x/slashing/keeper" - "cosmossdk.io/x/slashing/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/testutil" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - OpWeightMsgUnjail = "op_weight_msg_unjail" - - DefaultWeightMsgUnjail = 100 -) - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - registry codectypes.InterfaceRegistry, - appParams simtypes.AppParams, - cdc codec.JSONCodec, - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k keeper.Keeper, - sk types.StakingKeeper, -) simulation.WeightedOperations { - var weightMsgUnjail int - appParams.GetOrGenerate(OpWeightMsgUnjail, &weightMsgUnjail, nil, func(_ *rand.Rand) { - weightMsgUnjail = DefaultWeightMsgUnjail - }) - - return simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgUnjail, - SimulateMsgUnjail(codec.NewProtoCodec(registry), txGen, ak, bk, k, sk), - ), - } -} - -// SimulateMsgUnjail generates a MsgUnjail with random values -func SimulateMsgUnjail( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k keeper.Keeper, - sk types.StakingKeeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgUnjail{}) - - allVals, err := sk.GetAllValidators(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get all validators"), nil, err - } - - validator, ok := testutil.RandSliceElem(r, allVals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator is not ok"), nil, nil // skip - } - - bz, err := sk.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to convert validator address to bytes"), nil, err - } - - simAccount, found := simtypes.FindAccount(accs, sdk.AccAddress(bz)) - if !found { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to find account"), nil, nil // skip - } - - if !validator.IsJailed() { - // TODO: due to this condition this message is almost, if not always, skipped ! - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator is not jailed"), nil, nil - } - - consAddr, err := validator.GetConsAddr() - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get validator consensus key"), nil, err - } - info, _ := k.ValidatorSigningInfo.Get(ctx, consAddr) - - selfDel, _ := sk.Delegation(ctx, simAccount.Address, bz) - if selfDel == nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "self delegation is nil"), nil, nil // skip - } - - account := ak.GetAccount(ctx, sdk.AccAddress(bz)) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - fees, err := simtypes.RandomFees(r, spendable) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate fees"), nil, nil - } - - msg := types.NewMsgUnjail(validator.GetOperator()) - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - simAccount.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to generate mock tx"), nil, err - } - - _, res, err := app.SimDeliver(txGen.TxEncoder(), tx) - - // result should fail if: - // - validator cannot be unjailed due to tombstone - // - validator is still in jailed period - // - self delegation too low - if info.Tombstoned || - ctx.HeaderInfo().Time.Before(info.JailedUntil) || - selfDel.GetShares().IsNil() || - validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) { - if res != nil && err == nil { - if info.Tombstoned { - return simtypes.NewOperationMsg(msg, true, ""), nil, errors.New("validator should not have been unjailed if validator tombstoned") - } - if ctx.HeaderInfo().Time.Before(info.JailedUntil) { - return simtypes.NewOperationMsg(msg, true, ""), nil, errors.New("validator unjailed while validator still in jail period") - } - if selfDel.GetShares().IsNil() || - validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) { - return simtypes.NewOperationMsg(msg, true, ""), nil, errors.New("validator unjailed even though self-delegation too low") - } - } - // msg failed as expected - return simtypes.NewOperationMsg(msg, false, ""), nil, nil - } - - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, errors.New(res.Log) - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, nil - } -} diff --git a/x/staking/client/cli/tx_test.go b/x/staking/client/cli/tx_test.go index 6a39cde2f711..c63bf53ee2b4 100644 --- a/x/staking/client/cli/tx_test.go +++ b/x/staking/client/cli/tx_test.go @@ -149,7 +149,6 @@ func (s *CLITestSuite) TestPrepareConfigForTxCreateValidator() { } for _, tc := range tests { - tc := tc s.Run(tc.name, func() { fs, _ := cli.CreateValidatorMsgFlagSet(ip) fs.String(flags.FlagName, "", "name of private key with which to sign the gentx") @@ -296,7 +295,6 @@ func (s *CLITestSuite) TestNewCreateValidatorCmd() { }, } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) if tc.expectErrMsg != "" { @@ -419,8 +417,6 @@ func (s *CLITestSuite) TestNewEditValidatorCmd() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) if tc.expectErrMsg != "" { diff --git a/x/staking/depinject.go b/x/staking/depinject.go index e1e7a5844960..28012965b4df 100644 --- a/x/staking/depinject.go +++ b/x/staking/depinject.go @@ -17,6 +17,7 @@ import ( "cosmossdk.io/x/staking/types" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simsx" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -80,7 +81,7 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { in.ConsensusAddressCodec, in.CometInfoService, ) - m := NewAppModule(in.Cdc, k, in.AccountKeeper, in.BankKeeper) + m := NewAppModule(in.Cdc, k) return ModuleOutputs{StakingKeeper: k, Module: m} } @@ -130,20 +131,23 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { simulation.RandomizedGenState(simState) } -// ProposalMsgs returns msgs used for governance proposals for simulations. -func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { - return simulation.ProposalMsgs() -} - // RegisterStoreDecoder registers a decoder for staking module's types func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) } -// WeightedOperations returns the all the staking module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - simState.AppParams, simState.Cdc, simState.TxConfig, - am.accountKeeper, am.bankKeeper, am.keeper, - ) +// ProposalMsgsX returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_update_params", 100), simulation.MsgUpdateParamsFactory()) +} + +// WeightedOperationsX returns the all the staking module operations with their respective weights. +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_create_validator", 100), simulation.MsgCreateValidatorFactory(am.keeper)) + reg.Add(weights.Get("msg_delegate", 100), simulation.MsgDelegateFactory(am.keeper)) + reg.Add(weights.Get("msg_undelegate", 100), simulation.MsgUndelegateFactory(am.keeper)) + reg.Add(weights.Get("msg_edit_validator", 5), simulation.MsgEditValidatorFactory(am.keeper)) + reg.Add(weights.Get("msg_begin_redelegate", 100), simulation.MsgBeginRedelegateFactory(am.keeper)) + reg.Add(weights.Get("msg_cancel_unbonding_delegation", 100), simulation.MsgCancelUnbondingDelegationFactory(am.keeper)) + reg.Add(weights.Get("msg_rotate_cons_pubkey", 100), simulation.MsgRotateConsPubKeyFactory(am.keeper)) } diff --git a/x/staking/genesis_test.go b/x/staking/genesis_test.go index ce7eba2ac28b..f7bf349d5a66 100644 --- a/x/staking/genesis_test.go +++ b/x/staking/genesis_test.go @@ -44,8 +44,6 @@ func TestValidateGenesis(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { genesisState := types.DefaultGenesisState() tt.mutate(genesisState) diff --git a/x/staking/go.mod b/x/staking/go.mod index 066f8a1f58bc..abd74a6042b0 100644 --- a/x/staking/go.mod +++ b/x/staking/go.mod @@ -5,7 +5,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 @@ -26,7 +26,6 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 google.golang.org/grpc v1.66.2 google.golang.org/protobuf v1.34.2 - gotest.tools/v3 v3.5.1 ) require ( @@ -111,7 +110,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -165,11 +164,12 @@ require ( ) require ( - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect github.com/google/uuid v1.6.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect + gotest.tools/v3 v3.5.1 // indirect ) replace github.com/cosmos/cosmos-sdk => ../../. diff --git a/x/staking/go.sum b/x/staking/go.sum index cd6b45de5cf6..1f881f41bb27 100644 --- a/x/staking/go.sum +++ b/x/staking/go.sum @@ -4,8 +4,8 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +14,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -400,8 +400,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/staking/keeper/grpc_query.go b/x/staking/keeper/grpc_query.go index 99030babfbeb..e55671f34c9e 100644 --- a/x/staking/keeper/grpc_query.go +++ b/x/staking/keeper/grpc_query.go @@ -411,7 +411,7 @@ func (k Querier) DelegatorUnbondingDelegations(ctx context.Context, req *types.Q } // HistoricalInfo queries the historical info for given height -func (k Querier) HistoricalInfo(ctx context.Context, req *types.QueryHistoricalInfoRequest) (*types.QueryHistoricalInfoResponse, error) { // nolint:staticcheck // SA1019: deprecated endpoint +func (k Querier) HistoricalInfo(ctx context.Context, req *types.QueryHistoricalInfoRequest) (*types.QueryHistoricalInfoResponse, error) { //nolint:staticcheck // SA1019: deprecated endpoint if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } diff --git a/x/staking/keeper/msg_server_test.go b/x/staking/keeper/msg_server_test.go index f436b2ebda00..b5d92d62f535 100644 --- a/x/staking/keeper/msg_server_test.go +++ b/x/staking/keeper/msg_server_test.go @@ -314,7 +314,6 @@ func (s *KeeperTestSuite) TestMsgCreateValidator() { }, } for _, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { if tc.expPanic { require.PanicsWithValue(tc.expPanicMsg, func() { @@ -496,7 +495,6 @@ func (s *KeeperTestSuite) TestMsgEditValidator() { }, } for _, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { _, err := msgServer.EditValidator(tc.ctx, tc.input) if tc.expErr { @@ -614,7 +612,6 @@ func (s *KeeperTestSuite) TestMsgDelegate() { } for _, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { _, err := msgServer.Delegate(ctx, tc.input) if tc.expErr { @@ -782,7 +779,6 @@ func (s *KeeperTestSuite) TestMsgBeginRedelegate() { } for _, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { _, err := msgServer.BeginRedelegate(ctx, tc.input) if tc.expErr { @@ -906,7 +902,6 @@ func (s *KeeperTestSuite) TestMsgUndelegate() { } for _, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { _, err := msgServer.Undelegate(ctx, tc.input) if tc.expErr { @@ -1068,7 +1063,6 @@ func (s *KeeperTestSuite) TestMsgCancelUnbondingDelegation() { } for _, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { _, err := msgServer.CancelUnbondingDelegation(ctx, tc.input) if tc.expErr { @@ -1233,7 +1227,6 @@ func (s *KeeperTestSuite) TestMsgUpdateParams() { } for _, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { _, err := msgServer.UpdateParams(ctx, tc.input) if tc.expErrMsg != "" { diff --git a/x/staking/module.go b/x/staking/module.go index cddb3ba4c4d2..52b5313ed15b 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -43,24 +43,15 @@ var ( // AppModule implements an application module for the staking module. type AppModule struct { - cdc codec.Codec - keeper *keeper.Keeper - accountKeeper types.AccountKeeper - bankKeeper types.BankKeeper + cdc codec.Codec + keeper *keeper.Keeper } // NewAppModule creates a new AppModule object -func NewAppModule( - cdc codec.Codec, - keeper *keeper.Keeper, - ak types.AccountKeeper, - bk types.BankKeeper, -) AppModule { +func NewAppModule(cdc codec.Codec, keeper *keeper.Keeper) AppModule { return AppModule{ - cdc: cdc, - keeper: keeper, - accountKeeper: ak, - bankKeeper: bk, + cdc: cdc, + keeper: keeper, } } diff --git a/x/staking/simulation/decoder_test.go b/x/staking/simulation/decoder_test.go index 897219b86cce..cfdf2adf19a1 100644 --- a/x/staking/simulation/decoder_test.go +++ b/x/staking/simulation/decoder_test.go @@ -46,7 +46,6 @@ func TestDecodeStore(t *testing.T) { {"other", ""}, } for i, tt := range tests { - i, tt := i, tt t.Run(tt.name, func(t *testing.T) { switch i { case len(tests) - 1: diff --git a/x/staking/simulation/genesis.go b/x/staking/simulation/genesis.go index da5f694941d3..9808c3f43086 100644 --- a/x/staking/simulation/genesis.go +++ b/x/staking/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" "time" @@ -108,11 +106,5 @@ func RandomizedGenState(simState *module.SimulationState) { } stakingGenesis := types.NewGenesisState(params, validators, delegations) - - bz, err := json.MarshalIndent(&stakingGenesis.Params, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated staking parameters:\n%s\n", bz) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(stakingGenesis) } diff --git a/x/staking/simulation/genesis_test.go b/x/staking/simulation/genesis_test.go index d6350a037b28..d07553c0c156 100644 --- a/x/staking/simulation/genesis_test.go +++ b/x/staking/simulation/genesis_test.go @@ -109,8 +109,6 @@ func TestRandomizedGenState1(t *testing.T) { } for _, tt := range tests { - tt := tt - require.Panicsf(t, func() { simulation.RandomizedGenState(&tt.simState) }, tt.panicMsg) } } diff --git a/x/staking/simulation/msg_factory.go b/x/staking/simulation/msg_factory.go new file mode 100644 index 000000000000..31c35cddd507 --- /dev/null +++ b/x/staking/simulation/msg_factory.go @@ -0,0 +1,384 @@ +package simulation + +import ( + "context" + "slices" + "time" + + "cosmossdk.io/math" + "cosmossdk.io/x/staking/keeper" + "cosmossdk.io/x/staking/types" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/simsx" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func MsgCreateValidatorFactory(k *keeper.Keeper) simsx.SimMsgFactoryFn[*types.MsgCreateValidator] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgCreateValidator) { + r := testData.Rand() + withoutValidators := simsx.SimAccountFilterFn(func(a simsx.SimAccount) bool { + _, err := k.GetValidator(ctx, sdk.ValAddress(a.Address)) + return err != nil + }) + withoutConsAddrUsed := simsx.SimAccountFilterFn(func(a simsx.SimAccount) bool { + consPubKey := sdk.GetConsAddress(a.ConsKey.PubKey()) + _, err := k.GetValidatorByConsAddr(ctx, consPubKey) + return err != nil + }) + bondDenom := must(k.BondDenom(ctx)) + valOper := testData.AnyAccount(reporter, withoutValidators, withoutConsAddrUsed, simsx.WithDenomBalance(bondDenom)) + if reporter.IsSkipped() { + return nil, nil + } + + newPubKey := valOper.ConsKey.PubKey() + assertKeyUnused(ctx, reporter, k, newPubKey) + if reporter.IsSkipped() { + return nil, nil + } + + selfDelegation := valOper.LiquidBalance().RandSubsetCoin(reporter, bondDenom) + description := types.NewDescription( + r.StringN(10), + r.StringN(10), + r.StringN(10), + r.StringN(10), + r.StringN(10), + ) + + maxCommission := math.LegacyNewDecWithPrec(int64(r.IntInRange(0, 100)), 2) + commission := types.NewCommissionRates( + r.DecN(maxCommission), + maxCommission, + r.DecN(maxCommission), + ) + + addr := must(k.ValidatorAddressCodec().BytesToString(valOper.Address)) + msg, err := types.NewMsgCreateValidator(addr, newPubKey, selfDelegation, description, commission, math.OneInt()) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + + return []simsx.SimAccount{valOper}, msg + } +} + +func MsgDelegateFactory(k *keeper.Keeper) simsx.SimMsgFactoryFn[*types.MsgDelegate] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgDelegate) { + r := testData.Rand() + bondDenom := must(k.BondDenom(ctx)) + val := randomValidator(ctx, reporter, k, r) + if reporter.IsSkipped() { + return nil, nil + } + + if val.InvalidExRate() { + reporter.Skip("validator's invalid exchange rate") + return nil, nil + } + sender := testData.AnyAccount(reporter) + delegation := sender.LiquidBalance().RandSubsetCoin(reporter, bondDenom) + return []simsx.SimAccount{sender}, types.NewMsgDelegate(sender.AddressBech32, val.GetOperator(), delegation) + } +} + +func MsgUndelegateFactory(k *keeper.Keeper) simsx.SimMsgFactoryFn[*types.MsgUndelegate] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgUndelegate) { + r := testData.Rand() + bondDenom := must(k.BondDenom(ctx)) + val := randomValidator(ctx, reporter, k, r) + if reporter.IsSkipped() { + return nil, nil + } + + // select delegator and amount for undelegate + valAddr := must(k.ValidatorAddressCodec().StringToBytes(val.GetOperator())) + delegations := must(k.GetValidatorDelegations(ctx, valAddr)) + if delegations == nil { + reporter.Skip("no delegation entries") + return nil, nil + } + // get random delegator from validator + delegation := delegations[r.Intn(len(delegations))] + delAddr := delegation.GetDelegatorAddr() + delegator := testData.GetAccount(reporter, delAddr) + + if hasMaxUD := must(k.HasMaxUnbondingDelegationEntries(ctx, delegator.Address, valAddr)); hasMaxUD { + reporter.Skipf("max unbodings") + return nil, nil + } + + totalBond := val.TokensFromShares(delegation.GetShares()).TruncateInt() + if !totalBond.IsPositive() { + reporter.Skip("total bond is negative") + return nil, nil + } + + unbondAmt := must(r.PositiveSDKIntn(totalBond)) + msg := types.NewMsgUndelegate(delAddr, val.GetOperator(), sdk.NewCoin(bondDenom, unbondAmt)) + return []simsx.SimAccount{delegator}, msg + } +} + +func MsgEditValidatorFactory(k *keeper.Keeper) simsx.SimMsgFactoryFn[*types.MsgEditValidator] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgEditValidator) { + r := testData.Rand() + val := randomValidator(ctx, reporter, k, r) + if reporter.IsSkipped() { + return nil, nil + } + + newCommissionRate := r.DecN(val.Commission.MaxRate) + if err := val.Commission.ValidateNewRate(newCommissionRate, simsx.BlockTime(ctx)); err != nil { + // skip as the commission is invalid + reporter.Skip("invalid commission rate") + return nil, nil + } + valOpAddrBz := must(k.ValidatorAddressCodec().StringToBytes(val.GetOperator())) + valOper := testData.GetAccountbyAccAddr(reporter, valOpAddrBz) + d := types.NewDescription(r.StringN(10), r.StringN(10), r.StringN(10), r.StringN(10), r.StringN(10)) + + msg := types.NewMsgEditValidator(val.GetOperator(), d, &newCommissionRate, nil) + return []simsx.SimAccount{valOper}, msg + } +} + +func MsgBeginRedelegateFactory(k *keeper.Keeper) simsx.SimMsgFactoryFn[*types.MsgBeginRedelegate] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgBeginRedelegate) { + bondDenom := must(k.BondDenom(ctx)) + if !testData.IsSendEnabledDenom(bondDenom) { + reporter.Skip("bond denom send not enabled") + return nil, nil + } + + r := testData.Rand() + // select random validator as src + vals := must(k.GetAllValidators(ctx)) + if len(vals) < 2 { + reporter.Skip("insufficient number of validators") + return nil, nil + } + srcVal := simsx.OneOf(r, vals) + srcValOpAddrBz := must(k.ValidatorAddressCodec().StringToBytes(srcVal.GetOperator())) + delegations := must(k.GetValidatorDelegations(ctx, srcValOpAddrBz)) + if delegations == nil { + reporter.Skip("no delegations") + return nil, nil + } + // get random delegator from src validator + delegation := simsx.OneOf(r, delegations) + totalBond := srcVal.TokensFromShares(delegation.GetShares()).TruncateInt() + if !totalBond.IsPositive() { + reporter.Skip("total bond is negative") + return nil, nil + } + redAmount, err := r.PositiveSDKIntn(totalBond) + if err != nil || redAmount.IsZero() { + reporter.Skip("unable to generate positive amount") + return nil, nil + } + + // check if the shares truncate to zero + shares := must(srcVal.SharesFromTokens(redAmount)) + if srcVal.TokensFromShares(shares).TruncateInt().IsZero() { + reporter.Skip("shares truncate to zero") + return nil, nil + } + + // pick a random delegator + delAddr := delegation.GetDelegatorAddr() + delAddrBz := must(testData.AddressCodec().StringToBytes(delAddr)) + if hasRecRedel := must(k.HasReceivingRedelegation(ctx, delAddrBz, srcValOpAddrBz)); hasRecRedel { + reporter.Skip("receiving redelegation is not allowed") + return nil, nil + } + delegator := testData.GetAccountbyAccAddr(reporter, delAddrBz) + if reporter.IsSkipped() { + return nil, nil + } + + // get random destination validator + destVal := simsx.OneOf(r, vals) + if srcVal.Equal(&destVal) { + destVal = simsx.OneOf(r, slices.DeleteFunc(vals, func(v types.Validator) bool { return srcVal.Equal(&v) })) + } + if destVal.InvalidExRate() { + reporter.Skip("invalid delegation rate") + return nil, nil + } + + destAddrBz := must(k.ValidatorAddressCodec().StringToBytes(destVal.GetOperator())) + if hasMaxRedel := must(k.HasMaxRedelegationEntries(ctx, delAddrBz, srcValOpAddrBz, destAddrBz)); hasMaxRedel { + reporter.Skip("maximum redelegation entries reached") + return nil, nil + } + + msg := types.NewMsgBeginRedelegate( + delAddr, srcVal.GetOperator(), destVal.GetOperator(), + sdk.NewCoin(bondDenom, redAmount), + ) + return []simsx.SimAccount{delegator}, msg + } +} + +func MsgCancelUnbondingDelegationFactory(k *keeper.Keeper) simsx.SimMsgFactoryFn[*types.MsgCancelUnbondingDelegation] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgCancelUnbondingDelegation) { + r := testData.Rand() + val := randomValidator(ctx, reporter, k, r) + if reporter.IsSkipped() { + return nil, nil + } + if val.IsJailed() || val.InvalidExRate() { + reporter.Skip("validator is jailed") + return nil, nil + } + valOpAddrBz := must(k.ValidatorAddressCodec().StringToBytes(val.GetOperator())) + valOper := testData.GetAccountbyAccAddr(reporter, valOpAddrBz) + unbondingDelegation, err := k.GetUnbondingDelegation(ctx, valOper.Address, valOpAddrBz) + if err != nil { + reporter.Skip("no unbonding delegation") + return nil, nil + } + + // This is a temporary fix to make staking simulation pass. We should fetch + // the first unbondingDelegationEntry that matches the creationHeight, because + // currently the staking msgServer chooses the first unbondingDelegationEntry + // with the matching creationHeight. + // + // ref: https://github.com/cosmos/cosmos-sdk/issues/12932 + creationHeight := unbondingDelegation.Entries[r.Intn(len(unbondingDelegation.Entries))].CreationHeight + + var unbondingDelegationEntry types.UnbondingDelegationEntry + for _, entry := range unbondingDelegation.Entries { + if entry.CreationHeight == creationHeight { + unbondingDelegationEntry = entry + break + } + } + if unbondingDelegationEntry.CompletionTime.Before(simsx.BlockTime(ctx)) { + reporter.Skip("unbonding delegation is already processed") + return nil, nil + } + + if !unbondingDelegationEntry.Balance.IsPositive() { + reporter.Skip("delegator receiving balance is negative") + return nil, nil + } + cancelBondAmt := r.Amount(unbondingDelegationEntry.Balance) + if cancelBondAmt.IsZero() { + reporter.Skip("cancelBondAmt amount is zero") + return nil, nil + } + + msg := types.NewMsgCancelUnbondingDelegation( + valOper.AddressBech32, + val.GetOperator(), + unbondingDelegationEntry.CreationHeight, + sdk.NewCoin(must(k.BondDenom(ctx)), cancelBondAmt), + ) + + return []simsx.SimAccount{valOper}, msg + } +} + +func MsgRotateConsPubKeyFactory(k *keeper.Keeper) simsx.SimMsgFactoryFn[*types.MsgRotateConsPubKey] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgRotateConsPubKey) { + r := testData.Rand() + val := randomValidator(ctx, reporter, k, r) + if reporter.IsSkipped() { + return nil, nil + } + if val.Status != types.Bonded || val.ConsensusPower(sdk.DefaultPowerReduction) == 0 { + reporter.Skip("validator not bonded.") + return nil, nil + } + valOpAddrBz := must(k.ValidatorAddressCodec().StringToBytes(val.GetOperator())) + valOper := testData.GetAccountbyAccAddr(reporter, valOpAddrBz) + otherAccount := testData.AnyAccount(reporter, simsx.ExcludeAddresses(valOper.AddressBech32)) + + consAddress := must(k.ConsensusAddressCodec().BytesToString(must(val.GetConsAddr()))) + accAddress := must(k.ConsensusAddressCodec().BytesToString(otherAccount.ConsKey.PubKey().Address())) + if consAddress == accAddress { + reporter.Skip("new pubkey and current pubkey should be different") + return nil, nil + } + if !valOper.LiquidBalance().BlockAmount(must(k.Params.Get(ctx)).KeyRotationFee) { + reporter.Skip("not enough balance to pay for key rotation fee") + return nil, nil + } + if err := k.ExceedsMaxRotations(ctx, valOpAddrBz); err != nil { + reporter.Skip("rotations limit reached within unbonding period") + return nil, nil + } + // check whether the new cons key associated with another validator + newConsAddr := sdk.ConsAddress(otherAccount.ConsKey.PubKey().Address()) + + if _, err := k.GetValidatorByConsAddr(ctx, newConsAddr); err == nil { + reporter.Skip("cons key already used") + return nil, nil + } + msg := must(types.NewMsgRotateConsPubKey(val.GetOperator(), otherAccount.ConsKey.PubKey())) + + // check if there's another key rotation for this same key in the same block + for _, r := range must(k.GetBlockConsPubKeyRotationHistory(ctx)) { + if r.NewConsPubkey.Compare(msg.NewPubkey) == 0 { + reporter.Skip("cons key already used in this block") + return nil, nil + } + } + return []simsx.SimAccount{valOper}, msg + } +} + +// MsgUpdateParamsFactory creates a gov proposal for param updates +func MsgUpdateParamsFactory() simsx.SimMsgFactoryFn[*types.MsgUpdateParams] { + return func(_ context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgUpdateParams) { + r := testData.Rand() + params := types.DefaultParams() + // do not modify denom or staking will break + params.HistoricalEntries = r.Uint32InRange(0, 1000) + params.MaxEntries = r.Uint32InRange(1, 1000) + params.MaxValidators = r.Uint32InRange(1, 1000) + params.UnbondingTime = time.Duration(r.Timestamp().UnixNano()) + // modifying commission rate can cause issues for proposals within the same block + // params.MinCommissionRate = r.DecN(sdkmath.LegacyNewDec(1)) + + return nil, &types.MsgUpdateParams{ + Authority: testData.ModuleAccountAddress(reporter, "gov"), + Params: params, + } + } +} + +func randomValidator(ctx context.Context, reporter simsx.SimulationReporter, k *keeper.Keeper, r *simsx.XRand) types.Validator { + vals, err := k.GetAllValidators(ctx) + if err != nil || len(vals) == 0 { + reporter.Skipf("unable to get validators or empty list: %s", err) + return types.Validator{} + } + return simsx.OneOf(r, vals) +} + +// skips execution if there's another key rotation for the same key in the same block +func assertKeyUnused(ctx context.Context, reporter simsx.SimulationReporter, k *keeper.Keeper, newPubKey cryptotypes.PubKey) { + allRotations, err := k.GetBlockConsPubKeyRotationHistory(ctx) + if err != nil { + reporter.Skipf("cannot get block cons key rotation history: %s", err.Error()) + return + } + for _, r := range allRotations { + if r.NewConsPubkey.Compare(newPubKey) != 0 { + reporter.Skip("cons key already used in this block") + return + } + } +} + +func must[T any](r T, err error) T { + if err != nil { + panic(err) + } + return r +} diff --git a/x/staking/simulation/operations.go b/x/staking/simulation/operations.go deleted file mode 100644 index 83ca16fb43c6..000000000000 --- a/x/staking/simulation/operations.go +++ /dev/null @@ -1,873 +0,0 @@ -package simulation - -import ( - "bytes" - "fmt" - "math/rand" - - "cosmossdk.io/math" - "cosmossdk.io/x/staking/keeper" - "cosmossdk.io/x/staking/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/testutil" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - DefaultWeightMsgCreateValidator int = 100 - DefaultWeightMsgEditValidator int = 5 - DefaultWeightMsgDelegate int = 100 - DefaultWeightMsgUndelegate int = 100 - DefaultWeightMsgBeginRedelegate int = 100 - DefaultWeightMsgCancelUnbondingDelegation int = 100 - DefaultWeightMsgRotateConsPubKey int = 100 - - OpWeightMsgCreateValidator = "op_weight_msg_create_validator" - OpWeightMsgEditValidator = "op_weight_msg_edit_validator" - OpWeightMsgDelegate = "op_weight_msg_delegate" - OpWeightMsgUndelegate = "op_weight_msg_undelegate" - OpWeightMsgBeginRedelegate = "op_weight_msg_begin_redelegate" - OpWeightMsgCancelUnbondingDelegation = "op_weight_msg_cancel_unbonding_delegation" - OpWeightMsgRotateConsPubKey = "op_weight_msg_rotate_cons_pubkey" -) - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - appParams simtypes.AppParams, - cdc codec.JSONCodec, - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, -) simulation.WeightedOperations { - var ( - weightMsgCreateValidator int - weightMsgEditValidator int - weightMsgDelegate int - weightMsgUndelegate int - weightMsgBeginRedelegate int - weightMsgCancelUnbondingDelegation int - weightMsgRotateConsPubKey int - ) - - appParams.GetOrGenerate(OpWeightMsgCreateValidator, &weightMsgCreateValidator, nil, func(_ *rand.Rand) { - weightMsgCreateValidator = DefaultWeightMsgCreateValidator - }) - - appParams.GetOrGenerate(OpWeightMsgEditValidator, &weightMsgEditValidator, nil, func(_ *rand.Rand) { - weightMsgEditValidator = DefaultWeightMsgEditValidator - }) - - appParams.GetOrGenerate(OpWeightMsgDelegate, &weightMsgDelegate, nil, func(_ *rand.Rand) { - weightMsgDelegate = DefaultWeightMsgDelegate - }) - - appParams.GetOrGenerate(OpWeightMsgUndelegate, &weightMsgUndelegate, nil, func(_ *rand.Rand) { - weightMsgUndelegate = DefaultWeightMsgUndelegate - }) - - appParams.GetOrGenerate(OpWeightMsgBeginRedelegate, &weightMsgBeginRedelegate, nil, func(_ *rand.Rand) { - weightMsgBeginRedelegate = DefaultWeightMsgBeginRedelegate - }) - - appParams.GetOrGenerate(OpWeightMsgCancelUnbondingDelegation, &weightMsgCancelUnbondingDelegation, nil, func(_ *rand.Rand) { - weightMsgCancelUnbondingDelegation = DefaultWeightMsgCancelUnbondingDelegation - }) - - appParams.GetOrGenerate(OpWeightMsgRotateConsPubKey, &weightMsgRotateConsPubKey, nil, func(_ *rand.Rand) { - weightMsgRotateConsPubKey = DefaultWeightMsgRotateConsPubKey - }) - - return simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgCreateValidator, - SimulateMsgCreateValidator(txGen, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightMsgEditValidator, - SimulateMsgEditValidator(txGen, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightMsgDelegate, - SimulateMsgDelegate(txGen, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightMsgUndelegate, - SimulateMsgUndelegate(txGen, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightMsgBeginRedelegate, - SimulateMsgBeginRedelegate(txGen, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightMsgCancelUnbondingDelegation, - SimulateMsgCancelUnbondingDelegate(txGen, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightMsgRotateConsPubKey, - SimulateMsgRotateConsPubKey(txGen, ak, bk, k), - ), - } -} - -// SimulateMsgCreateValidator generates a MsgCreateValidator with random values -func SimulateMsgCreateValidator( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgCreateValidator{}) - - simAccount, _ := simtypes.RandomAcc(r, accs) - address := sdk.ValAddress(simAccount.Address) - - // ensure the validator doesn't exist already - _, err := k.GetValidator(ctx, address) - if err == nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator already exists"), nil, nil - } - - consPubKey := sdk.GetConsAddress(simAccount.ConsKey.PubKey()) - _, err = k.GetValidatorByConsAddr(ctx, consPubKey) - if err == nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cons key already used"), nil, nil - } - - denom, err := k.BondDenom(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "bond denom not found"), nil, err - } - - balance := bk.GetBalance(ctx, simAccount.Address, denom).Amount - if !balance.IsPositive() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "balance is negative"), nil, nil - } - - amount, err := simtypes.RandPositiveInt(r, balance) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate positive amount"), nil, err - } - - selfDelegation := sdk.NewCoin(denom, amount) - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - var fees sdk.Coins - - coins, hasNeg := spendable.SafeSub(selfDelegation) - if !hasNeg { - fees, err = simtypes.RandomFees(r, coins) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate fees"), nil, err - } - } - - description := types.NewDescription( - simtypes.RandStringOfLength(r, 10), - simtypes.RandStringOfLength(r, 10), - simtypes.RandStringOfLength(r, 10), - simtypes.RandStringOfLength(r, 10), - simtypes.RandStringOfLength(r, 10), - ) - - maxCommission := math.LegacyNewDecWithPrec(int64(simtypes.RandIntBetween(r, 0, 100)), 2) - commission := types.NewCommissionRates( - simtypes.RandomDecAmount(r, maxCommission), - maxCommission, - simtypes.RandomDecAmount(r, maxCommission), - ) - - addr, err := k.ValidatorAddressCodec().BytesToString(address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate validator address"), nil, err - } - - msg, err := types.NewMsgCreateValidator(addr, simAccount.ConsKey.PubKey(), selfDelegation, description, commission, math.OneInt()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to create CreateValidator message"), nil, err - } - - // check if there's another key rotation for this same key in the same block - allRotations, err := k.GetBlockConsPubKeyRotationHistory(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cannot get block cons key rotation history"), nil, err - } - for _, r := range allRotations { - if r.NewConsPubkey.Compare(msg.Pubkey) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cons key already used in this block"), nil, nil - } - } - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - ModuleName: types.ModuleName, - } - - return simulation.GenAndDeliverTx(txCtx, fees) - } -} - -// SimulateMsgEditValidator generates a MsgEditValidator with random values -func SimulateMsgEditValidator( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgEditValidator{}) - - vals, err := k.GetAllValidators(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get validators"), nil, err - } - - if len(vals) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "number of validators equal zero"), nil, nil - } - - val, ok := testutil.RandSliceElem(r, vals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to pick a validator"), nil, nil - } - - address := val.GetOperator() - newCommissionRate := simtypes.RandomDecAmount(r, val.Commission.MaxRate) - - if err := val.Commission.ValidateNewRate(newCommissionRate, ctx.HeaderInfo().Time); err != nil { - // skip as the commission is invalid - return simtypes.NoOpMsg(types.ModuleName, msgType, "invalid commission rate"), nil, nil - } - - bz, err := k.ValidatorAddressCodec().StringToBytes(val.GetOperator()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator address bytes"), nil, err - } - - simAccount, found := simtypes.FindAccount(accs, sdk.AccAddress(bz)) - if !found { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to find account"), nil, fmt.Errorf("validator %s not found", val.GetOperator()) - } - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - description := types.NewDescription( - simtypes.RandStringOfLength(r, 10), - simtypes.RandStringOfLength(r, 10), - simtypes.RandStringOfLength(r, 10), - simtypes.RandStringOfLength(r, 10), - simtypes.RandStringOfLength(r, 10), - ) - - msg := types.NewMsgEditValidator(address, description, &newCommissionRate, nil) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// SimulateMsgDelegate generates a MsgDelegate with random values -func SimulateMsgDelegate( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgDelegate{}) - denom, err := k.BondDenom(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "bond denom not found"), nil, err - } - - vals, err := k.GetAllValidators(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get validators"), nil, err - } - - if len(vals) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "number of validators equal zero"), nil, nil - } - - simAccount, _ := simtypes.RandomAcc(r, accs) - val, ok := testutil.RandSliceElem(r, vals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to pick a validator"), nil, nil - } - - if val.InvalidExRate() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator's invalid echange rate"), nil, nil - } - - amount := bk.GetBalance(ctx, simAccount.Address, denom).Amount - if !amount.IsPositive() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "balance is negative"), nil, nil - } - - amount, err = simtypes.RandPositiveInt(r, amount) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate positive amount"), nil, err - } - - bondAmt := sdk.NewCoin(denom, amount) - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - var fees sdk.Coins - - coins, hasNeg := spendable.SafeSub(bondAmt) - if !hasNeg { - fees, err = simtypes.RandomFees(r, coins) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate fees"), nil, err - } - } - - accAddr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting account string address"), nil, err - } - msg := types.NewMsgDelegate(accAddr, val.GetOperator(), bondAmt) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - ModuleName: types.ModuleName, - } - - return simulation.GenAndDeliverTx(txCtx, fees) - } -} - -// SimulateMsgUndelegate generates a MsgUndelegate with random values -func SimulateMsgUndelegate( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgUndelegate{}) - - vals, err := k.GetAllValidators(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get validators"), nil, err - } - - if len(vals) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "number of validators equal zero"), nil, nil - } - - val, ok := testutil.RandSliceElem(r, vals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator is not ok"), nil, nil - } - - valAddr, err := k.ValidatorAddressCodec().StringToBytes(val.GetOperator()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator address bytes"), nil, err - } - delegations, err := k.GetValidatorDelegations(ctx, valAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator delegations"), nil, nil - } - - if delegations == nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "keeper does have any delegation entries"), nil, nil - } - - // get random delegator from validator - delegation := delegations[r.Intn(len(delegations))] - delAddr := delegation.GetDelegatorAddr() - - delAddrBz, err := ak.AddressCodec().StringToBytes(delAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting delegator address bytes"), nil, err - } - - hasMaxUD, err := k.HasMaxUnbondingDelegationEntries(ctx, delAddrBz, valAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting max unbonding delegation entries"), nil, err - } - - if hasMaxUD { - return simtypes.NoOpMsg(types.ModuleName, msgType, "keeper does have a max unbonding delegation entries"), nil, nil - } - - totalBond := val.TokensFromShares(delegation.GetShares()).TruncateInt() - if !totalBond.IsPositive() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "total bond is negative"), nil, nil - } - - unbondAmt, err := simtypes.RandPositiveInt(r, totalBond) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "invalid unbond amount"), nil, err - } - - if unbondAmt.IsZero() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unbond amount is zero"), nil, nil - } - - bondDenom, err := k.BondDenom(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "bond denom not found"), nil, err - } - - msg := types.NewMsgUndelegate( - delAddr, val.GetOperator(), sdk.NewCoin(bondDenom, unbondAmt), - ) - - if !bk.IsSendEnabledDenom(ctx, bondDenom) { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "bond denom send not enabled"), nil, nil - } - - // need to retrieve the simulation account associated with delegation to retrieve PrivKey - var simAccount simtypes.Account - - for _, simAcc := range accs { - if simAcc.Address.Equals(sdk.AccAddress(delAddrBz)) { - simAccount = simAcc - break - } - } - // if simaccount.PrivKey == nil, delegation address does not exist in accs. However, since smart contracts and module accounts can stake, we can ignore the error - if simAccount.PrivKey == nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "account private key is nil"), nil, nil - } - - account := ak.GetAccount(ctx, delAddrBz) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// SimulateMsgCancelUnbondingDelegate generates a MsgCancelUnbondingDelegate with random values -func SimulateMsgCancelUnbondingDelegate( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgCancelUnbondingDelegation{}) - - vals, err := k.GetAllValidators(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get validators"), nil, err - } - - if len(vals) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "number of validators equal zero"), nil, nil - } - - simAccount, _ := simtypes.RandomAcc(r, accs) - val, ok := testutil.RandSliceElem(r, vals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator is not ok"), nil, nil - } - - if val.IsJailed() || val.InvalidExRate() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator is jailed"), nil, nil - } - - valAddr, err := k.ValidatorAddressCodec().StringToBytes(val.GetOperator()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator address bytes"), nil, err - } - unbondingDelegation, err := k.GetUnbondingDelegation(ctx, simAccount.Address, valAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "account does have any unbonding delegation"), nil, nil - } - - // This is a temporary fix to make staking simulation pass. We should fetch - // the first unbondingDelegationEntry that matches the creationHeight, because - // currently the staking msgServer chooses the first unbondingDelegationEntry - // with the matching creationHeight. - // - // ref: https://github.com/cosmos/cosmos-sdk/issues/12932 - creationHeight := unbondingDelegation.Entries[r.Intn(len(unbondingDelegation.Entries))].CreationHeight - - var unbondingDelegationEntry types.UnbondingDelegationEntry - - for _, entry := range unbondingDelegation.Entries { - if entry.CreationHeight == creationHeight { - unbondingDelegationEntry = entry - break - } - } - - if unbondingDelegationEntry.CompletionTime.Before(ctx.HeaderInfo().Time) { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unbonding delegation is already processed"), nil, nil - } - - if !unbondingDelegationEntry.Balance.IsPositive() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "delegator receiving balance is negative"), nil, nil - } - - cancelBondAmt := simtypes.RandomAmount(r, unbondingDelegationEntry.Balance) - - if cancelBondAmt.IsZero() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cancelBondAmt amount is zero"), nil, nil - } - - bondDenom, err := k.BondDenom(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "bond denom not found"), nil, err - } - - accAddr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting account string address"), nil, err - } - msg := types.NewMsgCancelUnbondingDelegation( - accAddr, val.GetOperator(), unbondingDelegationEntry.CreationHeight, sdk.NewCoin(bondDenom, cancelBondAmt), - ) - - spendable := bk.SpendableCoins(ctx, simAccount.Address) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// SimulateMsgBeginRedelegate generates a MsgBeginRedelegate with random values -func SimulateMsgBeginRedelegate( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgBeginRedelegate{}) - - allVals, err := k.GetAllValidators(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get validators"), nil, err - } - - if len(allVals) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "number of validators equal zero"), nil, nil - } - - srcVal, ok := testutil.RandSliceElem(r, allVals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to pick validator"), nil, nil - } - - srcAddr, err := k.ValidatorAddressCodec().StringToBytes(srcVal.GetOperator()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator address bytes"), nil, err - } - delegations, err := k.GetValidatorDelegations(ctx, srcAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator delegations"), nil, nil - } - - if delegations == nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "keeper does have any delegation entries"), nil, nil - } - - // get random delegator from src validator - delegation := delegations[r.Intn(len(delegations))] - delAddr := delegation.GetDelegatorAddr() - - delAddrBz, err := ak.AddressCodec().StringToBytes(delAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting delegator address bytes"), nil, err - } - - hasRecRedel, err := k.HasReceivingRedelegation(ctx, delAddrBz, srcAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting receiving redelegation"), nil, err - } - - if hasRecRedel { - return simtypes.NoOpMsg(types.ModuleName, msgType, "receveing redelegation is not allowed"), nil, nil // skip - } - - // get random destination validator - destVal, ok := testutil.RandSliceElem(r, allVals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to pick validator"), nil, nil - } - - destAddr, err := k.ValidatorAddressCodec().StringToBytes(destVal.GetOperator()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator address bytes"), nil, err - } - hasMaxRedel, err := k.HasMaxRedelegationEntries(ctx, delAddrBz, srcAddr, destAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting max redelegation entries"), nil, err - } - - if bytes.Equal(srcAddr, destAddr) || destVal.InvalidExRate() || hasMaxRedel { - return simtypes.NoOpMsg(types.ModuleName, msgType, "checks failed"), nil, nil - } - - totalBond := srcVal.TokensFromShares(delegation.GetShares()).TruncateInt() - if !totalBond.IsPositive() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "total bond is negative"), nil, nil - } - - redAmt, err := simtypes.RandPositiveInt(r, totalBond) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate positive amount"), nil, err - } - - if redAmt.IsZero() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "amount is zero"), nil, nil - } - - // check if the shares truncate to zero - shares, err := srcVal.SharesFromTokens(redAmt) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "invalid shares"), nil, err - } - - if srcVal.TokensFromShares(shares).TruncateInt().IsZero() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "shares truncate to zero"), nil, nil // skip - } - - // need to retrieve the simulation account associated with delegation to retrieve PrivKey - var simAccount simtypes.Account - - for _, simAcc := range accs { - if simAcc.Address.Equals(sdk.AccAddress(delAddrBz)) { - simAccount = simAcc - break - } - } - - // if simaccount.PrivKey == nil, delegation address does not exist in accs. However, since smart contracts and module accounts can stake, we can ignore the error - if simAccount.PrivKey == nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "account private key is nil"), nil, nil - } - - account := ak.GetAccount(ctx, delAddrBz) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - bondDenom, err := k.BondDenom(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "bond denom not found"), nil, err - } - - if !bk.IsSendEnabledDenom(ctx, bondDenom) { - return simtypes.NoOpMsg(types.ModuleName, msgType, "bond denom send not enabled"), nil, nil - } - - msg := types.NewMsgBeginRedelegate( - delAddr, srcVal.GetOperator(), destVal.GetOperator(), - sdk.NewCoin(bondDenom, redAmt), - ) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -func SimulateMsgRotateConsPubKey(txGen client.TxConfig, ak types.AccountKeeper, bk types.BankKeeper, k *keeper.Keeper) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgRotateConsPubKey{}) - - vals, err := k.GetAllValidators(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get validators"), nil, err - } - - if len(vals) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "number of validators equal zero"), nil, nil - } - - val, ok := testutil.RandSliceElem(r, vals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to pick a validator"), nil, nil - } - - if val.Status != types.Bonded || val.ConsensusPower(sdk.DefaultPowerReduction) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator not bonded."), nil, nil - } - - valAddr := val.GetOperator() - valBytes, err := k.ValidatorAddressCodec().StringToBytes(valAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator address bytes"), nil, err - } - - simAccount, found := simtypes.FindAccount(accs, sdk.AccAddress(valBytes)) - if !found { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to find account"), nil, fmt.Errorf("validator %s not found", val.GetOperator()) - } - - cons, err := val.GetConsAddr() - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cannot get conskey"), nil, err - } - consAddress, err := k.ConsensusAddressCodec().BytesToString(cons) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting consensus address"), nil, err - } - - acc, _ := simtypes.RandomAcc(r, accs) - accAddress, err := k.ConsensusAddressCodec().BytesToString(acc.ConsKey.PubKey().Address()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting consensus address"), nil, err - } - if consAddress == accAddress { - return simtypes.NoOpMsg(types.ModuleName, msgType, "new pubkey and current pubkey should be different"), nil, nil - } - - account := ak.GetAccount(ctx, simAccount.Address) - if account == nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to find account"), nil, nil - } - - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - params, err := k.Params.Get(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cannot get params"), nil, err - } - - if !spendable.IsAllGTE(sdk.NewCoins(params.KeyRotationFee)) { - return simtypes.NoOpMsg(types.ModuleName, msgType, "not enough balance to pay fee"), nil, nil - } - - if err := k.ExceedsMaxRotations(ctx, valBytes); err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "rotations limit reached within unbonding period"), nil, nil - } - - _, err = k.GetValidatorByConsAddr(ctx, cons) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cannot get validator"), nil, err - } - - // check whether the new cons key associated with another validator - newConsAddr := sdk.ConsAddress(acc.ConsKey.PubKey().Address()) - _, err = k.GetValidatorByConsAddr(ctx, newConsAddr) - if err == nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cons key already used"), nil, nil - } - - msg, err := types.NewMsgRotateConsPubKey(valAddr, acc.ConsKey.PubKey()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to build msg"), nil, err - } - - // check if there's another key rotation for this same key in the same block - allRotations, err := k.GetBlockConsPubKeyRotationHistory(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cannot get block cons key rotation history"), nil, err - } - for _, r := range allRotations { - if r.NewConsPubkey.Compare(msg.NewPubkey) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cons key already used in this block"), nil, nil - } - } - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} diff --git a/x/staking/simulation/proposals.go b/x/staking/simulation/proposals.go deleted file mode 100644 index 36afe6db90d3..000000000000 --- a/x/staking/simulation/proposals.go +++ /dev/null @@ -1,56 +0,0 @@ -package simulation - -import ( - "context" - "math/rand" - "time" - - coreaddress "cosmossdk.io/core/address" - "cosmossdk.io/x/staking/types" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - DefaultWeightMsgUpdateParams int = 100 - - OpWeightMsgUpdateParams = "op_weight_msg_update_params" -) - -// ProposalMsgs defines the module weighted proposals' contents -func ProposalMsgs() []simtypes.WeightedProposalMsg { - return []simtypes.WeightedProposalMsg{ - simulation.NewWeightedProposalMsgX( - OpWeightMsgUpdateParams, - DefaultWeightMsgUpdateParams, - SimulateMsgUpdateParams, - ), - } -} - -// SimulateMsgUpdateParams returns a random MsgUpdateParams -func SimulateMsgUpdateParams(_ context.Context, r *rand.Rand, _ []simtypes.Account, addressCodec coreaddress.Codec) (sdk.Msg, error) { - // use the default gov module account address as authority - var authority sdk.AccAddress = address.Module("gov") - - params := types.DefaultParams() - params.HistoricalEntries = uint32(simtypes.RandIntBetween(r, 0, 1000)) - params.MaxEntries = uint32(simtypes.RandIntBetween(r, 1, 1000)) - params.MaxValidators = uint32(simtypes.RandIntBetween(r, 1, 1000)) - params.UnbondingTime = time.Duration(simtypes.RandTimestamp(r).UnixNano()) - // changes to MinCommissionRate or BondDenom create issues for in flight messages or state operations - - addr, err := addressCodec.BytesToString(authority) - if err != nil { - return nil, err - } - - return &types.MsgUpdateParams{ - Authority: addr, - Params: params, - }, nil -} diff --git a/x/staking/simulation/proposals_test.go b/x/staking/simulation/proposals_test.go deleted file mode 100644 index 4373ae15b290..000000000000 --- a/x/staking/simulation/proposals_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package simulation_test - -import ( - "context" - "math/rand" - "testing" - - "gotest.tools/v3/assert" - - "cosmossdk.io/x/staking/simulation" - "cosmossdk.io/x/staking/types" - - codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" -) - -func TestProposalMsgs(t *testing.T) { - // initialize parameters - s := rand.NewSource(1) - r := rand.New(s) - - accounts := simtypes.RandomAccounts(r, 3) - addressCodec := codectestutil.CodecOptions{}.GetAddressCodec() - // execute ProposalMsgs function - weightedProposalMsgs := simulation.ProposalMsgs() - assert.Assert(t, len(weightedProposalMsgs) == 1) - - w0 := weightedProposalMsgs[0] - - // tests w0 interface: - assert.Equal(t, simulation.OpWeightMsgUpdateParams, w0.AppParamsKey()) - assert.Equal(t, simulation.DefaultWeightMsgUpdateParams, w0.DefaultWeight()) - - msg, err := w0.MsgSimulatorFn()(context.Background(), r, accounts, addressCodec) - assert.NilError(t, err) - msgUpdateParams, ok := msg.(*types.MsgUpdateParams) - assert.Assert(t, ok) - - addr, err := addressCodec.BytesToString(address.Module("gov")) - assert.NilError(t, err) - - assert.Equal(t, addr, msgUpdateParams.Authority) - assert.Equal(t, "stake", msgUpdateParams.Params.BondDenom) - assert.Equal(t, uint32(905), msgUpdateParams.Params.MaxEntries) - assert.Equal(t, uint32(540), msgUpdateParams.Params.HistoricalEntries) - assert.Equal(t, uint32(151), msgUpdateParams.Params.MaxValidators) - assert.Equal(t, "2417694h42m25s", msgUpdateParams.Params.UnbondingTime.String()) -} diff --git a/x/staking/types/authz_test.go b/x/staking/types/authz_test.go index 1a8a66420dc0..c4ab9dc7bbd8 100644 --- a/x/staking/types/authz_test.go +++ b/x/staking/types/authz_test.go @@ -408,7 +408,6 @@ func TestAuthzAuthorizations(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.msg, func(t *testing.T) { delAuth, err := stakingtypes.NewStakeAuthorization(tc.allowed, tc.denied, tc.msgType, tc.limit, valAddressCodec) require.NoError(t, err) diff --git a/x/tx/CHANGELOG.md b/x/tx/CHANGELOG.md index 7dfbc54a8a73..d75a44787385 100644 --- a/x/tx/CHANGELOG.md +++ b/x/tx/CHANGELOG.md @@ -35,6 +35,7 @@ Since v0.13.0, x/tx follows Cosmos SDK semver: https://github.com/cosmos/cosmos- ### Improvements +* [#21712](https://github.com/cosmos/cosmos-sdk/pull/21712) Add `AminoNameAsTypeURL` option to Amino JSON encoder. * [#21073](https://github.com/cosmos/cosmos-sdk/pull/21073) In Context use sync.Map `getSignersFuncs` map from concurrent writes, we also need to call Validate when using the legacy app. ## [v0.13.3](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.3) - 2024-04-22 diff --git a/x/tx/decode/unknown_test.go b/x/tx/decode/unknown_test.go index dddabbb40267..7d901a5a29e2 100644 --- a/x/tx/decode/unknown_test.go +++ b/x/tx/decode/unknown_test.go @@ -233,7 +233,6 @@ func TestRejectUnknownFieldsRepeated(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { protoBlob, err := proto.Marshal(tt.in) if err != nil { @@ -294,7 +293,6 @@ func TestRejectUnknownFields_allowUnknownNonCriticals(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { blob, err := proto.Marshal(tt.in) if err != nil { @@ -491,7 +489,6 @@ func TestRejectUnknownFieldsNested(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { protoBlob, err := proto.Marshal(tt.in) if err != nil { @@ -627,7 +624,6 @@ func TestRejectUnknownFieldsFlat(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { blob, err := proto.Marshal(tt.in) if err != nil { diff --git a/x/tx/signing/aminojson/json_marshal.go b/x/tx/signing/aminojson/json_marshal.go index f276cb39d23e..52defcca6357 100644 --- a/x/tx/signing/aminojson/json_marshal.go +++ b/x/tx/signing/aminojson/json_marshal.go @@ -32,6 +32,10 @@ type EncoderOptions struct { // EnumAsString when set will encode enums as strings instead of integers. // Caution: Enabling this option produce different sign bytes. EnumAsString bool + // AminoNameAsTypeURL when set will use the amino name as the type URL in the JSON output. + // It is useful when using the Amino JSON encoder for non Amino purposes, + // such as JSON RPC. + AminoNameAsTypeURL bool // TypeResolver is used to resolve protobuf message types by TypeURL when marshaling any packed messages. TypeResolver signing.TypeResolver // FileResolver is used to resolve protobuf file descriptors TypeURL when TypeResolver fails. @@ -50,6 +54,7 @@ type Encoder struct { doNotSortFields bool indent string enumsAsString bool + aminoNameAsTypeURL bool } // NewEncoder returns a new Encoder capable of serializing protobuf messages to JSON using the Amino JSON encoding @@ -80,11 +85,12 @@ func NewEncoder(options EncoderOptions) Encoder { "google.protobuf.Duration": marshalDuration, "google.protobuf.Any": marshalAny, }, - fileResolver: options.FileResolver, - typeResolver: options.TypeResolver, - doNotSortFields: options.DoNotSortFields, - indent: options.Indent, - enumsAsString: options.EnumAsString, + fileResolver: options.FileResolver, + typeResolver: options.TypeResolver, + doNotSortFields: options.DoNotSortFields, + indent: options.Indent, + enumsAsString: options.EnumAsString, + aminoNameAsTypeURL: options.AminoNameAsTypeURL, } return enc } @@ -187,9 +193,17 @@ func (enc Encoder) beginMarshal(msg protoreflect.Message, writer io.Writer, isAn ) if isAny { - name, named = getMessageAminoNameAny(msg), true + if enc.aminoNameAsTypeURL { + name, named = getMessageTypeURL(msg), true + } else { + name, named = getMessageAminoNameAny(msg), true + } } else { name, named = getMessageAminoName(msg) + if enc.aminoNameAsTypeURL { + // do not override named + name = getMessageTypeURL(msg) + } } if named { diff --git a/x/tx/signing/aminojson/json_marshal_test.go b/x/tx/signing/aminojson/json_marshal_test.go index a51b83bb49da..29d2f8cf8f59 100644 --- a/x/tx/signing/aminojson/json_marshal_test.go +++ b/x/tx/signing/aminojson/json_marshal_test.go @@ -355,3 +355,62 @@ func TestEnumAsString(t *testing.T) { } }`, string(bz)) } + +func TestAminoNameAsTypeURL(t *testing.T) { + encoder := aminojson.NewEncoder(aminojson.EncoderOptions{Indent: " ", AminoNameAsTypeURL: true}) + + msg := &testpb.ABitOfEverything{ + Message: &testpb.NestedMessage{ + Foo: "test", + Bar: 0, // this is the default value and should be omitted from output + }, + Enum: testpb.AnEnum_ONE, + Repeated: []int32{3, -7, 2, 6, 4}, + Str: `abcxyz"foo"def`, + Bool: true, + Bytes: []byte{0, 1, 2, 3}, + I32: -15, + F32: 1001, + U32: 1200, + Si32: -376, + Sf32: -1000, + I64: 14578294827584932, + F64: 9572348124213523654, + U64: 4759492485, + Si64: -59268425823934, + Sf64: -659101379604211154, + } + + bz, err := encoder.Marshal(msg) + require.NoError(t, err) + fmt.Println(string(bz)) + require.Equal(t, `{ + "type": "/testpb.ABitOfEverything", + "value": { + "bool": true, + "bytes": "AAECAw==", + "enum": 1, + "f32": 1001, + "f64": "9572348124213523654", + "i32": -15, + "i64": "14578294827584932", + "message": { + "foo": "test" + }, + "repeated": [ + 3, + -7, + 2, + 6, + 4 + ], + "sf32": -1000, + "sf64": "-659101379604211154", + "si32": -376, + "si64": "-59268425823934", + "str": "abcxyz\"foo\"def", + "u32": 1200, + "u64": "4759492485" + } +}`, string(bz)) +} diff --git a/x/tx/signing/aminojson/options.go b/x/tx/signing/aminojson/options.go index 0eecedb88731..cf9110aef3ae 100644 --- a/x/tx/signing/aminojson/options.go +++ b/x/tx/signing/aminojson/options.go @@ -25,7 +25,6 @@ func getMessageAminoName(msg protoreflect.Message) (string, bool) { // getMessageAminoName returns the amino name of a message if it has been set by the `amino.name` option. // If the message does not have an amino name, then it returns the msg url. -// If it cannot get the msg url, then it returns false. func getMessageAminoNameAny(msg protoreflect.Message) string { messageOptions := msg.Descriptor().Options() if proto.HasExtension(messageOptions, amino.E_Name) { @@ -33,6 +32,11 @@ func getMessageAminoNameAny(msg protoreflect.Message) string { return name.(string) } + return getMessageTypeURL(msg) +} + +// getMessageTypeURL returns the msg url. +func getMessageTypeURL(msg protoreflect.Message) string { msgURL := "/" + string(msg.Descriptor().FullName()) if msgURL != "/" { return msgURL diff --git a/x/tx/signing/textual/any_test.go b/x/tx/signing/textual/any_test.go index da64acf0df79..0bcce5988151 100644 --- a/x/tx/signing/textual/any_test.go +++ b/x/tx/signing/textual/any_test.go @@ -88,7 +88,6 @@ func TestDynamicpb(t *testing.T) { } for _, tc := range testcases { - tc := tc t.Run(tc.name, func(t *testing.T) { any, err := anyutil.New(tc.msg) require.NoError(t, err) diff --git a/x/tx/signing/textual/dec_test.go b/x/tx/signing/textual/dec_test.go index f8c7b3ebe2f4..152e2b71619e 100644 --- a/x/tx/signing/textual/dec_test.go +++ b/x/tx/signing/textual/dec_test.go @@ -27,7 +27,6 @@ func TestDecJSONTestcases(t *testing.T) { require.NoError(t, err) for _, tc := range testcases { - tc := tc t.Run(tc[0], func(t *testing.T) { r, err := textual.GetFieldValueRenderer(fieldDescriptorFromName("SDKDEC")) require.NoError(t, err) diff --git a/x/tx/signing/textual/handler_test.go b/x/tx/signing/textual/handler_test.go index 70c2ea124a9f..13e15b981845 100644 --- a/x/tx/signing/textual/handler_test.go +++ b/x/tx/signing/textual/handler_test.go @@ -32,7 +32,6 @@ func TestDispatcher(t *testing.T) { } for _, tc := range testcases { - tc := tc t.Run(tc.name, func(t *testing.T) { textual, err := textual.NewSignModeHandler(textual.SignModeOptions{CoinMetadataQuerier: EmptyCoinMetadataQuerier}) require.NoError(t, err) diff --git a/x/upgrade/go.mod b/x/upgrade/go.mod index 2be842e1dc9b..e1d2c471b700 100644 --- a/x/upgrade/go.mod +++ b/x/upgrade/go.mod @@ -4,7 +4,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.3 cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 @@ -42,7 +42,7 @@ require ( cloud.google.com/go/storage v1.43.0 // indirect cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/math v1.3.0 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.0 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -145,7 +145,7 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/x/upgrade/go.sum b/x/upgrade/go.sum index 2f1b0306c453..51948090d43b 100644 --- a/x/upgrade/go.sum +++ b/x/upgrade/go.sum @@ -194,8 +194,8 @@ cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1V cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -204,8 +204,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 h1:XQJj9Dv9Gtze0l2TF79BU5lkP6MkUveTUuKICmxoz+o= cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190/go.mod h1:7WUGupOvmlHJoIMBz1JbObQxeo6/TDiuDBxmtod8HRg= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -710,8 +710,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/x/upgrade/keeper/grpc_query_test.go b/x/upgrade/keeper/grpc_query_test.go index 2f799677273f..df97a2e72249 100644 --- a/x/upgrade/keeper/grpc_query_test.go +++ b/x/upgrade/keeper/grpc_query_test.go @@ -204,8 +204,6 @@ func (suite *UpgradeTestSuite) TestModuleVersions() { suite.Require().NoError(err) for _, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { suite.SetupTest() // reset diff --git a/x/upgrade/keeper/keeper_test.go b/x/upgrade/keeper/keeper_test.go index 16b88d418a75..66297a3fe6d9 100644 --- a/x/upgrade/keeper/keeper_test.go +++ b/x/upgrade/keeper/keeper_test.go @@ -189,8 +189,6 @@ func (s *KeeperTestSuite) TestScheduleUpgrade() { } for _, tc := range cases { - tc := tc - s.Run(tc.name, func() { // reset suite s.SetupTest() diff --git a/x/upgrade/types/plan_test.go b/x/upgrade/types/plan_test.go index 423f12b1d47f..668528cfa69d 100644 --- a/x/upgrade/types/plan_test.go +++ b/x/upgrade/types/plan_test.go @@ -42,7 +42,6 @@ func TestPlanString(t *testing.T) { } for name, tc := range cases { - tc := tc // copy to local variable for scopelint t.Run(name, func(t *testing.T) { s := tc.p.String() require.Equal(t, tc.expect, s) @@ -93,7 +92,6 @@ func TestPlanValid(t *testing.T) { } for name, tc := range cases { - tc := tc // copy to local variable for scopelint t.Run(name, func(t *testing.T) { err := tc.p.ValidateBasic() if tc.valid { @@ -142,7 +140,6 @@ func TestShouldExecute(t *testing.T) { } for name, tc := range cases { - tc := tc // copy to local variable for scopelint t.Run(name, func(t *testing.T) { should := tc.p.ShouldExecute(tc.ctxHeight) assert.Equal(t, tc.expected, should) diff --git a/x/upgrade/types/storeloader_test.go b/x/upgrade/types/storeloader_test.go index d14d160f01ed..45e0b81df9fc 100644 --- a/x/upgrade/types/storeloader_test.go +++ b/x/upgrade/types/storeloader_test.go @@ -93,7 +93,6 @@ func TestSetLoader(t *testing.T) { v := []byte("value") for name, tc := range cases { - tc := tc t.Run(name, func(t *testing.T) { // prepare a db with some data db := coretesting.NewMemDB()