diff --git a/Makefile b/Makefile index 75db4c1bae2..5f2be37e95a 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ export GO111MODULE = on # process build tags -build_tags = netgo +build_tags = netgo app_v2 ifeq ($(LEDGER_ENABLED),true) ifeq ($(OS),Windows_NT) GCCEXE = $(shell where gcc.exe 2> NUL) @@ -333,8 +333,8 @@ lint-fix: #? format: Run gofumpt and mispell format: - find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "./docs/client/statik/statik.go" -not -path "./tests/mocks/*" -not -name '*.pb.go' -not -name '*.pb.gw.go' | xargs gofumpt -w - find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "./docs/client/statik/statik.go" -not -path "./tests/mocks/*" -not -name '*.pb.go' -not -name '*.pb.gw.go' | xargs misspell -w + find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "./docs/client/statik/statik.go" -not -path "./tests/mocks/*" -not -name '*.pb.go' -not -name '*.pb.gw.go' -not -name '*.pulsar.go' | xargs gofumpt -w + find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "./docs/client/statik/statik.go" -not -path "./tests/mocks/*" -not -name '*.pb.go' -not -name '*.pb.gw.go' -not -name '*.pulsar.go' | xargs misspell -w .PHONY: format #? docs-lint: Lint markdown documentation files diff --git a/api/go.mod b/api/go.mod index 18b1ed4e575..bb9c5e76792 100644 --- a/api/go.mod +++ b/api/go.mod @@ -12,7 +12,6 @@ require ( github.com/cosmos/gogoproto v1.4.11 github.com/cosmos/ics23/go/api v0.0.0 google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a - google.golang.org/grpc v1.59.0 google.golang.org/protobuf v1.33.0 ) @@ -25,4 +24,5 @@ require ( golang.org/x/text v0.14.0 // indirect google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect + google.golang.org/grpc v1.59.0 // indirect ) diff --git a/api/mock/module/v1/module.pulsar.go b/api/mock/module/v1/module.pulsar.go new file mode 100644 index 00000000000..fa6e8e8cf10 --- /dev/null +++ b/api/mock/module/v1/module.pulsar.go @@ -0,0 +1,499 @@ +// Code generated by protoc-gen-go-pulsar. DO NOT EDIT. +package modulev1 + +import ( + _ "cosmossdk.io/api/cosmos/app/v1alpha1" + 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" + io "io" + reflect "reflect" + sync "sync" +) + +var ( + md_Module protoreflect.MessageDescriptor +) + +func init() { + file_mock_module_v1_module_proto_init() + md_Module = File_mock_module_v1_module_proto.Messages().ByName("Module") +} + +var _ protoreflect.Message = (*fastReflection_Module)(nil) + +type fastReflection_Module Module + +func (x *Module) ProtoReflect() protoreflect.Message { + return (*fastReflection_Module)(x) +} + +func (x *Module) slowProtoReflect() protoreflect.Message { + mi := &file_mock_module_v1_module_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_Module_messageType fastReflection_Module_messageType +var _ protoreflect.MessageType = fastReflection_Module_messageType{} + +type fastReflection_Module_messageType struct{} + +func (x fastReflection_Module_messageType) Zero() protoreflect.Message { + return (*fastReflection_Module)(nil) +} +func (x fastReflection_Module_messageType) New() protoreflect.Message { + return new(fastReflection_Module) +} +func (x fastReflection_Module_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_Module +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_Module) Descriptor() protoreflect.MessageDescriptor { + return md_Module +} + +// 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_Module) Type() protoreflect.MessageType { + return _fastReflection_Module_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_Module) New() protoreflect.Message { + return new(fastReflection_Module) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_Module) Interface() protoreflect.ProtoMessage { + return (*Module)(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_Module) 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_Module) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: mock.module.v1.Module")) + } + panic(fmt.Errorf("message mock.module.v1.Module 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_Module) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: mock.module.v1.Module")) + } + panic(fmt.Errorf("message mock.module.v1.Module 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_Module) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: mock.module.v1.Module")) + } + panic(fmt.Errorf("message mock.module.v1.Module 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_Module) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: mock.module.v1.Module")) + } + panic(fmt.Errorf("message mock.module.v1.Module 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_Module) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: mock.module.v1.Module")) + } + panic(fmt.Errorf("message mock.module.v1.Module 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_Module) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: mock.module.v1.Module")) + } + panic(fmt.Errorf("message mock.module.v1.Module 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_Module) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in mock.module.v1.Module", 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_Module) 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_Module) 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_Module) 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_Module) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*Module) + 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().(*Module) + 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().(*Module) + 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: Module: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: Module: 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, + } +} + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.0 +// protoc (unknown) +// source: mock/module/v1/module.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) +) + +// Module is the config object of the mock module. +type Module struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *Module) Reset() { + *x = Module{} + if protoimpl.UnsafeEnabled { + mi := &file_mock_module_v1_module_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Module) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Module) ProtoMessage() {} + +// Deprecated: Use Module.ProtoReflect.Descriptor instead. +func (*Module) Descriptor() ([]byte, []int) { + return file_mock_module_v1_module_proto_rawDescGZIP(), []int{0} +} + +var File_mock_module_v1_module_proto protoreflect.FileDescriptor + +var file_mock_module_v1_module_proto_rawDesc = []byte{ + 0x0a, 0x1b, 0x6d, 0x6f, 0x63, 0x6b, 0x2f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2f, 0x76, 0x31, + 0x2f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x6d, + 0x6f, 0x63, 0x6b, 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x20, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, + 0x37, 0x0a, 0x06, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x3a, 0x2d, 0xba, 0xc0, 0x96, 0xda, 0x01, + 0x27, 0x0a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x69, 0x62, 0x63, 0x2d, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, + 0x69, 0x6e, 0x67, 0x2f, 0x6d, 0x6f, 0x63, 0x6b, 0x42, 0xb1, 0x01, 0x0a, 0x12, 0x63, 0x6f, 0x6d, + 0x2e, 0x6d, 0x6f, 0x63, 0x6b, 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x42, + 0x0b, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x34, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2f, 0x69, 0x62, 0x63, 0x2d, 0x67, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x6d, 0x6f, 0x63, + 0x6b, 0x2f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x6d, 0x6f, 0x64, 0x75, + 0x6c, 0x65, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x4d, 0x4d, 0x58, 0xaa, 0x02, 0x0e, 0x4d, 0x6f, 0x63, + 0x6b, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0e, 0x4d, 0x6f, + 0x63, 0x6b, 0x5c, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1a, 0x4d, + 0x6f, 0x63, 0x6b, 0x5c, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, + 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x10, 0x4d, 0x6f, 0x63, 0x6b, + 0x3a, 0x3a, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_mock_module_v1_module_proto_rawDescOnce sync.Once + file_mock_module_v1_module_proto_rawDescData = file_mock_module_v1_module_proto_rawDesc +) + +func file_mock_module_v1_module_proto_rawDescGZIP() []byte { + file_mock_module_v1_module_proto_rawDescOnce.Do(func() { + file_mock_module_v1_module_proto_rawDescData = protoimpl.X.CompressGZIP(file_mock_module_v1_module_proto_rawDescData) + }) + return file_mock_module_v1_module_proto_rawDescData +} + +var file_mock_module_v1_module_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_mock_module_v1_module_proto_goTypes = []interface{}{ + (*Module)(nil), // 0: mock.module.v1.Module +} +var file_mock_module_v1_module_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_mock_module_v1_module_proto_init() } +func file_mock_module_v1_module_proto_init() { + if File_mock_module_v1_module_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_mock_module_v1_module_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Module); 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_mock_module_v1_module_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_mock_module_v1_module_proto_goTypes, + DependencyIndexes: file_mock_module_v1_module_proto_depIdxs, + MessageInfos: file_mock_module_v1_module_proto_msgTypes, + }.Build() + File_mock_module_v1_module_proto = out.File + file_mock_module_v1_module_proto_rawDesc = nil + file_mock_module_v1_module_proto_goTypes = nil + file_mock_module_v1_module_proto_depIdxs = nil +} diff --git a/go.mod b/go.mod index af15e62033f..6b327042ccd 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,9 @@ go 1.21 module github.com/cosmos/ibc-go/v8 +// Replace to local pin of capability to pick up depinject +replace github.com/cosmos/ibc-go/modules/capability => ./modules/capability + require ( cosmossdk.io/api v0.7.3 cosmossdk.io/client/v2 v2.0.0-beta.1 @@ -87,6 +90,7 @@ require ( github.com/fatih/color v1.15.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect diff --git a/go.sum b/go.sum index 97cf174e835..716b7970d90 100644 --- a/go.sum +++ b/go.sum @@ -364,8 +364,6 @@ github.com/cosmos/gogoproto v1.4.12 h1:vB6Lbe/rtnYGjQuFxkPiPYiCybqFT8QvLipDZP8Jp github.com/cosmos/gogoproto v1.4.12/go.mod h1:LnZob1bXRdUoqMMtwYlcR3wjiElmlC+FkjaZRv1/eLY= github.com/cosmos/iavl v1.0.1 h1:D+mYbcRO2wptYzOM1Hxl9cpmmHU1ZEt9T2Wv5nZTeUw= github.com/cosmos/iavl v1.0.1/go.mod h1:8xIUkgVvwvVrBu81scdPty+/Dx9GqwHnAvXz4cwF7RY= -github.com/cosmos/ibc-go/modules/capability v1.0.0 h1:r/l++byFtn7jHYa09zlAdSeevo8ci1mVZNO9+V0xsLE= -github.com/cosmos/ibc-go/modules/capability v1.0.0/go.mod h1:D81ZxzjZAe0ZO5ambnvn1qedsFQ8lOwtqicG6liLBco= github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= @@ -445,6 +443,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 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/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= 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= @@ -484,18 +484,19 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+ github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= -github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= +github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= +github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= -github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA= +github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= 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= diff --git a/modules/apps/27-interchain-accounts/depinject.go b/modules/apps/27-interchain-accounts/depinject.go index 0a3901cd224..1de75e0877c 100644 --- a/modules/apps/27-interchain-accounts/depinject.go +++ b/modules/apps/27-interchain-accounts/depinject.go @@ -12,8 +12,12 @@ import ( modulev1 "github.com/cosmos/ibc-go/api/ibc/applications/interchain_accounts/module/v1" capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper" - controllerKeeper "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/controller/keeper" - hostKeeper "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/host/keeper" + "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/controller" + controllerkeeper "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/controller/keeper" + controllertypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/controller/types" + "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/host" + hostkeeper "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/host/keeper" + hosttypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/host/types" "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/types" porttypes "github.com/cosmos/ibc-go/v8/modules/core/05-port/types" ) @@ -34,19 +38,23 @@ func init() { type ModuleInputs struct { depinject.In - Config *modulev1.Module - Cdc codec.Codec + // TODO: Config should define `controller_enabled` and `host_enabled` vars for keeper/module setup + Config *modulev1.Module + Cdc codec.Codec + + // TODO: runtime seems to expect that a module contains a single kvstore key. ControllerKey *storetypes.KVStoreKey HostKey *storetypes.KVStoreKey - Ics4Wrapper porttypes.ICS4Wrapper - ChannelKeeper types.ChannelKeeper - PortKeeper types.PortKeeper - ScopedKeeper capabilitykeeper.ScopedKeeper - AccountKeeper types.AccountKeeper + Ics4Wrapper porttypes.ICS4Wrapper + ChannelKeeper types.ChannelKeeper + PortKeeper types.PortKeeper + CapabilityKeeper *capabilitykeeper.Keeper + AccountKeeper types.AccountKeeper - MsgRouter types.MessageRouter - QueryRouter types.QueryRouter + MsgRouter types.MessageRouter + // TODO(remove optional): GRCPQueryRouter is not outputted into DI container on v0.50. It is on main. + QueryRouter types.QueryRouter `optional:"true"` // LegacySubspace is used solely for migration of x/params managed parameters LegacySubspace paramtypes.Subspace `optional:"true"` @@ -56,9 +64,10 @@ type ModuleInputs struct { type ModuleOutputs struct { depinject.Out - ControllerKeeper *controllerKeeper.Keeper - HostKeeper *hostKeeper.Keeper + ControllerKeeper *controllerkeeper.Keeper + HostKeeper *hostkeeper.Keeper Module appmodule.AppModule + IBCModuleRoutes []porttypes.IBCModuleRoute } // ProvideModule returns the 27-interchain-accounts outputs for dependency injection @@ -69,18 +78,21 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { authority = authtypes.NewModuleAddressOrBech32Address(in.Config.Authority) } - controllerkeeper := controllerKeeper.NewKeeper( + scopedControllerKeeper := in.CapabilityKeeper.ScopeToModule(controllertypes.SubModuleName) + controllerKeeper := controllerkeeper.NewKeeper( in.Cdc, in.ControllerKey, in.LegacySubspace, in.Ics4Wrapper, in.ChannelKeeper, in.PortKeeper, - in.ScopedKeeper, + scopedControllerKeeper, in.MsgRouter, authority.String(), ) - hostkeeper := hostKeeper.NewKeeper( + + scopedHostKeeper := in.CapabilityKeeper.ScopeToModule(hosttypes.SubModuleName) + hostKeeper := hostkeeper.NewKeeper( in.Cdc, in.HostKey, in.LegacySubspace, @@ -88,12 +100,27 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { in.ChannelKeeper, in.PortKeeper, in.AccountKeeper, - in.ScopedKeeper, + scopedHostKeeper, in.MsgRouter, in.QueryRouter, authority.String(), ) - m := NewAppModule(&controllerkeeper, &hostkeeper) - - return ModuleOutputs{ControllerKeeper: &controllerkeeper, HostKeeper: &hostkeeper, Module: m} + m := NewAppModule(&controllerKeeper, &hostKeeper) + + controllerModule := controller.NewIBCMiddleware(nil, controllerKeeper) + hostModule := host.NewIBCModule(hostKeeper) + + return ModuleOutputs{ + ControllerKeeper: &controllerKeeper, + HostKeeper: &hostKeeper, + Module: m, + IBCModuleRoutes: []porttypes.IBCModuleRoute{ + { + Name: controllertypes.SubModuleName, IBCModule: controllerModule, + }, + { + Name: hosttypes.SubModuleName, IBCModule: hostModule, + }, + }, + } } diff --git a/modules/apps/transfer/depinject.go b/modules/apps/transfer/depinject.go index 6e08d4f649e..b4cc18f7576 100644 --- a/modules/apps/transfer/depinject.go +++ b/modules/apps/transfer/depinject.go @@ -37,13 +37,13 @@ type ModuleInputs struct { Cdc codec.Codec Key *storetypes.KVStoreKey - Ics4Wrapper porttypes.ICS4Wrapper ChannelKeeper types.ChannelKeeper + Ics4Wrapper porttypes.ICS4Wrapper PortKeeper types.PortKeeper - AuthKeeper types.AccountKeeper - BankKeeper types.BankKeeper - ScopedKeeper capabilitykeeper.ScopedKeeper + AuthKeeper types.AccountKeeper + BankKeeper types.BankKeeper + CapabilityKeeper *capabilitykeeper.Keeper // LegacySubspace is used solely for migration of x/params managed parameters LegacySubspace paramtypes.Subspace `optional:"true"` @@ -53,8 +53,10 @@ type ModuleInputs struct { type ModuleOutputs struct { depinject.Out - TransferKeeper *keeper.Keeper + ScopedKeeper types.ScopedTransferKeeper + TransferKeeper keeper.Keeper Module appmodule.AppModule + IBCModuleRoute porttypes.IBCModuleRoute } // ProvideModule returns the transfer module outputs for dependency injection @@ -65,6 +67,7 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { authority = authtypes.NewModuleAddressOrBech32Address(in.Config.Authority) } + scopedKeeper := in.CapabilityKeeper.ScopeToModule(types.ModuleName) transferKeeper := keeper.NewKeeper( in.Cdc, in.Key, @@ -74,10 +77,17 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { in.PortKeeper, in.AuthKeeper, in.BankKeeper, - in.ScopedKeeper, + scopedKeeper, authority.String(), ) + m := NewAppModule(transferKeeper) + ibcModule := NewIBCModule(transferKeeper) - return ModuleOutputs{TransferKeeper: &transferKeeper, Module: m} + return ModuleOutputs{ + ScopedKeeper: types.ScopedTransferKeeper{ScopedKeeper: scopedKeeper}, + TransferKeeper: transferKeeper, + Module: m, + IBCModuleRoute: porttypes.IBCModuleRoute{Name: types.ModuleName, IBCModule: ibcModule}, + } } diff --git a/modules/apps/transfer/keeper/keeper_test.go b/modules/apps/transfer/keeper/keeper_test.go index 0d0da50c002..190314311aa 100644 --- a/modules/apps/transfer/keeper/keeper_test.go +++ b/modules/apps/transfer/keeper/keeper_test.go @@ -13,6 +13,8 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/cosmos/ibc-go/v8/modules/apps/transfer/keeper" "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" @@ -62,7 +64,7 @@ func (suite *KeeperTestSuite) TestNewKeeper() { suite.chainA.GetSimApp().AccountKeeper, suite.chainA.GetSimApp().BankKeeper, suite.chainA.GetSimApp().ScopedTransferKeeper, - suite.chainA.GetSimApp().ICAControllerKeeper.GetAuthority(), + authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) }, true}, {"failure: transfer module account does not exist", func() { @@ -76,7 +78,7 @@ func (suite *KeeperTestSuite) TestNewKeeper() { authkeeper.AccountKeeper{}, // empty account keeper suite.chainA.GetSimApp().BankKeeper, suite.chainA.GetSimApp().ScopedTransferKeeper, - suite.chainA.GetSimApp().ICAControllerKeeper.GetAuthority(), + authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) }, false}, {"failure: empty authority", func() { diff --git a/modules/apps/transfer/types/expected_keepers.go b/modules/apps/transfer/types/expected_keepers.go index e639a84606f..fdeb2023f2e 100644 --- a/modules/apps/transfer/types/expected_keepers.go +++ b/modules/apps/transfer/types/expected_keepers.go @@ -7,6 +7,7 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper" capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" connectiontypes "github.com/cosmos/ibc-go/v8/modules/core/03-connection/types" channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" @@ -61,3 +62,6 @@ type PortKeeper interface { type ParamSubspace interface { GetParamSet(ctx sdk.Context, ps paramtypes.ParamSet) } + +// ScopedTranferKeeper embeds x/capability's ScopedKeeper used for depinject module outputs. +type ScopedTransferKeeper struct{ capabilitykeeper.ScopedKeeper } diff --git a/modules/capability/module.go b/modules/capability/module.go index 64957b93cdb..1dd208a5eaa 100644 --- a/modules/capability/module.go +++ b/modules/capability/module.go @@ -6,9 +6,10 @@ import ( "fmt" "time" - "cosmossdk.io/core/appmodule" gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime" + "cosmossdk.io/core/appmodule" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" diff --git a/modules/core/02-client/types/router.go b/modules/core/02-client/types/router.go index c13449274c1..5c2dce2d37d 100644 --- a/modules/core/02-client/types/router.go +++ b/modules/core/02-client/types/router.go @@ -3,6 +3,7 @@ package types import ( "fmt" + "cosmossdk.io/depinject" storetypes "cosmossdk.io/store/types" "github.com/cosmos/ibc-go/v8/modules/core/exported" @@ -64,3 +65,18 @@ func (rtr *Router) GetRoute(clientID string) (exported.LightClientModule, bool) } return rtr.routes[clientType], true } + +var _ depinject.OnePerModuleType = (*LightClientModuleWrapper)(nil) + +// LightClientModuleWrapper is a wrapper struct used for depinject to register client modules on the router. +type LightClientModuleWrapper struct{ exported.LightClientModule } + +// NewLightClientModuleWrapper creates and returns a new LightClientModuleWrapper used for depinject. +func NewLightClientModuleWrapper(clientModule exported.LightClientModule) LightClientModuleWrapper { + return LightClientModuleWrapper{ + clientModule, + } +} + +// IsOnePerModuleType implements the depinject.OnePerModuleType interface. +func (LightClientModuleWrapper) IsOnePerModuleType() {} diff --git a/modules/core/05-port/types/module.go b/modules/core/05-port/types/module.go index 23fc5705233..feb170d9f08 100644 --- a/modules/core/05-port/types/module.go +++ b/modules/core/05-port/types/module.go @@ -1,6 +1,8 @@ package types import ( + "cosmossdk.io/depinject" + sdk "github.com/cosmos/cosmos-sdk/types" capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" @@ -9,6 +11,18 @@ import ( "github.com/cosmos/ibc-go/v8/modules/core/exported" ) +var _ depinject.ManyPerContainerType = (*IBCModuleRoute)(nil) + +// IBCModule defines a wrapper struct for depinject. This allows cosmos-sdk modules to output multiple IBCModules associated with a +// specific name used for a routing key. An example of this is 27-interchain-accounts which defines two IBCModules under a single cosmos-sdk module. +type IBCModuleRoute struct { + Name string + IBCModule IBCModule +} + +// IsManyPerContainerType implements the depinject.ManyPerContainerType interface. +func (IBCModuleRoute) IsManyPerContainerType() {} + // IBCModule defines an interface that implements all the callbacks // that modules must define as specified in ICS-26 type IBCModule interface { diff --git a/modules/core/depinject.go b/modules/core/depinject.go index 61424f65d54..df2d075726b 100644 --- a/modules/core/depinject.go +++ b/modules/core/depinject.go @@ -13,7 +13,13 @@ import ( modulev1 "github.com/cosmos/ibc-go/api/ibc/core/module/v1" capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" + channelkeeper "github.com/cosmos/ibc-go/v8/modules/core/04-channel/keeper" + portkeeper "github.com/cosmos/ibc-go/v8/modules/core/05-port/keeper" + porttypes "github.com/cosmos/ibc-go/v8/modules/core/05-port/types" + "github.com/cosmos/ibc-go/v8/modules/core/exported" ibckeeper "github.com/cosmos/ibc-go/v8/modules/core/keeper" + "github.com/cosmos/ibc-go/v8/modules/core/types" + ibctm "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" ) var _ depinject.OnePerModuleType = AppModule{} @@ -25,6 +31,7 @@ func init() { appmodule.Register( &modulev1.Module{}, appmodule.Provide(ProvideModule), + appmodule.Invoke(InvokeAddAppRoutes, InvokeAddClientRoutes), ) } @@ -36,9 +43,9 @@ type ModuleInputs struct { Cdc codec.Codec Key *storetypes.KVStoreKey - ConsensusHost clienttypes.ConsensusHost - UpgradeKeeper clienttypes.UpgradeKeeper - ScopedKeeper capabilitykeeper.ScopedKeeper + CapabilityKeeper *capabilitykeeper.Keeper + StakingKeeper clienttypes.StakingKeeper + UpgradeKeeper clienttypes.UpgradeKeeper // LegacySubspace is used solely for migration of x/params managed parameters LegacySubspace paramtypes.Subspace `optional:"true"` @@ -48,10 +55,16 @@ type ModuleInputs struct { type ModuleOutputs struct { depinject.Out - IbcKeeper *ibckeeper.Keeper - Module appmodule.AppModule + Module appmodule.AppModule + + IBCKeeper *ibckeeper.Keeper + ScopedIBCKeeper types.ScopedIBCKeeper + + ChannelKeeper *channelkeeper.Keeper + PortKeeper *portkeeper.Keeper } +// ProvideModule defines a depinject provider function to supply the module dependencies and return its outputs. func ProvideModule(in ModuleInputs) ModuleOutputs { // default to governance authority if not provided authority := authtypes.NewModuleAddress(govtypes.ModuleName) @@ -59,16 +72,44 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { authority = authtypes.NewModuleAddressOrBech32Address(in.Config.Authority) } + scopedKeeper := in.CapabilityKeeper.ScopeToModule(exported.ModuleName) + keeper := ibckeeper.NewKeeper( in.Cdc, in.Key, in.LegacySubspace, - in.ConsensusHost, + ibctm.NewConsensusHost(in.StakingKeeper), // NOTE: need to find a way to inject a ConsensusHost into DI container created outside context of app module. in.UpgradeKeeper, - in.ScopedKeeper, + scopedKeeper, authority.String(), ) m := NewAppModule(keeper) - return ModuleOutputs{IbcKeeper: keeper, Module: m} + return ModuleOutputs{ + Module: m, + IBCKeeper: keeper, + ChannelKeeper: keeper.ChannelKeeper, + PortKeeper: keeper.PortKeeper, + ScopedIBCKeeper: types.ScopedIBCKeeper{ScopedKeeper: scopedKeeper}, + } +} + +// InvokeAddAppRoutes defines a depinject Invoker for registering ibc application modules on the core ibc application router. +func InvokeAddAppRoutes(keeper *ibckeeper.Keeper, appRoutes []porttypes.IBCModuleRoute) { + ibcRouter := porttypes.NewRouter() + for _, route := range appRoutes { + ibcRouter.AddRoute(route.Name, route.IBCModule) + } + + keeper.SetRouter(ibcRouter) +} + +// InvokeAddClientRoutes defines a depinject Invoker for registering ibc light client modules on the core ibc client router. +// TODO: Maybe this should align with app router. i.e. create router here, add routes, and set on ibc keeper. +// For app_v1 this would be the same approach, just create clientRouter in app.go instead of implicit creation inside of ibc.NewKeeper() +func InvokeAddClientRoutes(keeper *ibckeeper.Keeper, clientRoutes map[string]clienttypes.LightClientModuleWrapper) { + router := keeper.ClientKeeper.GetRouter() + for modName, route := range clientRoutes { + router.AddRoute(modName, route.LightClientModule) + } } diff --git a/modules/core/keeper/keeper_test.go b/modules/core/keeper/keeper_test.go index 95f62bd110a..60e604c9271 100644 --- a/modules/core/keeper/keeper_test.go +++ b/modules/core/keeper/keeper_test.go @@ -133,7 +133,7 @@ func (suite *KeeperTestSuite) TestNewKeeper() { consensusHost = ibctm.NewConsensusHost(suite.chainA.GetSimApp().StakingKeeper) upgradeKeeper = suite.chainA.GetSimApp().UpgradeKeeper - scopedKeeper = suite.chainA.GetSimApp().ScopedIBCKeeper + scopedKeeper = suite.chainA.GetSimApp().GetScopedIBCKeeper() tc.malleate() diff --git a/modules/core/types/expected_interfaces.go b/modules/core/types/expected_interfaces.go index c6aca313696..a9321805f06 100644 --- a/modules/core/types/expected_interfaces.go +++ b/modules/core/types/expected_interfaces.go @@ -3,9 +3,14 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + + capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper" ) // ParamSubspace defines the expected Subspace interface for module parameters. type ParamSubspace interface { GetParamSet(ctx sdk.Context, ps paramtypes.ParamSet) } + +// ScopedIBCKeeper embeds x/capability's ScopedKeeper used for depinject module outputs. +type ScopedIBCKeeper struct{ capabilitykeeper.ScopedKeeper } diff --git a/modules/light-clients/06-solomachine/depinject.go b/modules/light-clients/06-solomachine/depinject.go index b1c12a84279..0c6931d8906 100644 --- a/modules/light-clients/06-solomachine/depinject.go +++ b/modules/light-clients/06-solomachine/depinject.go @@ -7,6 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" modulev1 "github.com/cosmos/ibc-go/api/ibc/lightclients/solomachine/module/v1" + clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" ) var _ depinject.OnePerModuleType = AppModule{} @@ -32,13 +33,13 @@ type ModuleInputs struct { type ModuleOutputs struct { depinject.Out - LightClientModule *LightClientModule - Module appmodule.AppModule + LightClientModuleWrapper clienttypes.LightClientModuleWrapper + Module appmodule.AppModule } // ProvideModule returns the 06-solomachine module outputs for dependency injection func ProvideModule(in ModuleInputs) ModuleOutputs { lightClientModule := NewLightClientModule(in.Cdc) m := NewAppModule(lightClientModule) - return ModuleOutputs{LightClientModule: &lightClientModule, Module: m} + return ModuleOutputs{LightClientModuleWrapper: clienttypes.NewLightClientModuleWrapper(&lightClientModule), Module: m} } diff --git a/modules/light-clients/07-tendermint/depinject.go b/modules/light-clients/07-tendermint/depinject.go index 58208649df9..1c2b3481588 100644 --- a/modules/light-clients/07-tendermint/depinject.go +++ b/modules/light-clients/07-tendermint/depinject.go @@ -9,6 +9,7 @@ import ( govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" modulev1 "github.com/cosmos/ibc-go/api/ibc/lightclients/tendermint/module/v1" + clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" ) var _ depinject.OnePerModuleType = AppModule{} @@ -35,8 +36,8 @@ type ModuleInputs struct { type ModuleOutputs struct { depinject.Out - LightClientModule *LightClientModule - Module appmodule.AppModule + LightClientModuleWrapper clienttypes.LightClientModuleWrapper + Module appmodule.AppModule } // ProvideModule returns the 07-tendermint module outputs for dependency injection @@ -49,5 +50,5 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { lightClientModule := NewLightClientModule(in.Cdc, authority.String()) m := NewAppModule(lightClientModule) - return ModuleOutputs{LightClientModule: &lightClientModule, Module: m} + return ModuleOutputs{LightClientModuleWrapper: clienttypes.NewLightClientModuleWrapper(&lightClientModule), Module: m} } diff --git a/proto/mock/module/v1/module.proto b/proto/mock/module/v1/module.proto new file mode 100644 index 00000000000..08eefbe94b8 --- /dev/null +++ b/proto/mock/module/v1/module.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +package mock.module.v1; + +import "cosmos/app/v1alpha1/module.proto"; + +// Module is the config object of the mock module. +message Module { + option (cosmos.app.v1alpha1.module) = { + go_import: "github.com/cosmos/ibc-go/testing/mock" + }; +} \ No newline at end of file diff --git a/testing/chain.go b/testing/chain.go index 5b59e78fe40..b3ec00147bd 100644 --- a/testing/chain.go +++ b/testing/chain.go @@ -27,7 +27,6 @@ import ( cmttypes "github.com/cometbft/cometbft/types" cmtversion "github.com/cometbft/cometbft/version" - capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper" capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" @@ -37,6 +36,7 @@ import ( "github.com/cosmos/ibc-go/v8/modules/core/types" ibctm "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" "github.com/cosmos/ibc-go/v8/testing/simapp" + testingtypes "github.com/cosmos/ibc-go/v8/testing/types" ) var MaxAccounts = 10 @@ -560,7 +560,7 @@ func MakeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) cmttypes.B // already exist. This function will fail testing on any resulting error. // NOTE: only creation of a capability for a transfer or mock port is supported // Other applications must bind to the port in InitGenesis or modify this code. -func (chain *TestChain) CreatePortCapability(scopedKeeper capabilitykeeper.ScopedKeeper, portID string) { +func (chain *TestChain) CreatePortCapability(scopedKeeper testingtypes.ScopedKeeper, portID string) { // check if the portId is already binded, if not bind it _, ok := chain.App.GetScopedIBCKeeper().GetCapability(chain.GetContext(), host.PortPath(portID)) if !ok { @@ -588,7 +588,7 @@ func (chain *TestChain) GetPortCapability(portID string) *capabilitytypes.Capabi // CreateChannelCapability binds and claims a capability for the given portID and channelID // if it does not already exist. This function will fail testing on any resulting error. The // scoped keeper passed in will claim the new capability. -func (chain *TestChain) CreateChannelCapability(scopedKeeper capabilitykeeper.ScopedKeeper, portID, channelID string) { +func (chain *TestChain) CreateChannelCapability(scopedKeeper testingtypes.ScopedKeeper, portID, channelID string) { capName := host.ChannelCapabilityPath(portID, channelID) // check if the portId is already binded, if not bind it _, ok := chain.App.GetScopedIBCKeeper().GetCapability(chain.GetContext(), capName) diff --git a/testing/mock/ack.go b/testing/mock/ack.go deleted file mode 100644 index 619ac098d44..00000000000 --- a/testing/mock/ack.go +++ /dev/null @@ -1,23 +0,0 @@ -package mock - -// EmptyAcknowledgement implements the exported.Acknowledgement interface and always returns an empty byte string as Response -type EmptyAcknowledgement struct { - Response []byte -} - -// NewEmptyAcknowledgement returns a new instance of EmptyAcknowledgement -func NewEmptyAcknowledgement() EmptyAcknowledgement { - return EmptyAcknowledgement{ - Response: []byte{}, - } -} - -// Success implements the Acknowledgement interface -func (EmptyAcknowledgement) Success() bool { - return true -} - -// Acknowledgement implements the Acknowledgement interface -func (EmptyAcknowledgement) Acknowledgement() []byte { - return []byte{} -} diff --git a/testing/mock/depinject.go b/testing/mock/depinject.go new file mode 100644 index 00000000000..114c4092bd0 --- /dev/null +++ b/testing/mock/depinject.go @@ -0,0 +1,62 @@ +package mock + +import ( + "cosmossdk.io/core/appmodule" + "cosmossdk.io/depinject" + storetypes "cosmossdk.io/store/types" + + modulev1 "github.com/cosmos/ibc-go/api/mock/module/v1" + capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper" + porttypes "github.com/cosmos/ibc-go/v8/modules/core/05-port/types" + ibckeeper "github.com/cosmos/ibc-go/v8/modules/core/keeper" +) + +func init() { + appmodule.Register( + &modulev1.Module{}, + appmodule.Provide(ProvideModule), + ) +} + +var _ depinject.OnePerModuleType = AppModule{} + +// IsOnePerModuleType implements the depinject.OnePerModuleType interface. +func (AppModule) IsOnePerModuleType() {} + +// ModuleInputs defines the core module inputs for depinject. +type ModuleInputs struct { + depinject.In + + Config *modulev1.Module + + // TODO: mock memKey is not directly used by the mock IBCModule but is included in app_v1 and used in some testing. + // Verify what tests are using this and if it can be removed here. It is certainly used ibccallbacks testing with mock contract keeper. + Key *storetypes.MemoryStoreKey + + CapabilityKeeper *capabilitykeeper.Keeper + IBCKeeper *ibckeeper.Keeper +} + +// ModuleOutputs defines the core module outputs for depinject. +type ModuleOutputs struct { + depinject.Out + + Module appmodule.AppModule + IBCModule IBCModule + IBCModuleRoute porttypes.IBCModuleRoute + ScopedKeeper ScopedMockKeeper +} + +// ProvideModule defines a depinject provider function to supply the module dependencies and return its outputs. +func ProvideModule(in ModuleInputs) ModuleOutputs { + scopedKeeper := in.CapabilityKeeper.ScopeToModule(ModuleName) + m := NewAppModule(in.IBCKeeper.PortKeeper) + ibcModule := NewIBCModule(&m, NewIBCApp(ModuleName, scopedKeeper)) + + return ModuleOutputs{ + Module: m, + IBCModule: ibcModule, + IBCModuleRoute: porttypes.IBCModuleRoute{Name: ModuleName, IBCModule: ibcModule}, + ScopedKeeper: ScopedMockKeeper{ScopedKeeper: scopedKeeper}, + } +} diff --git a/testing/mock/mock.go b/testing/mock/mock.go index 3a15d776a63..f5ad5b229df 100644 --- a/testing/mock/mock.go +++ b/testing/mock/mock.go @@ -1,27 +1,14 @@ package mock import ( - "encoding/json" "fmt" - "github.com/grpc-ecosystem/grpc-gateway/runtime" - "github.com/spf13/cobra" - - "cosmossdk.io/core/appmodule" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/module" - - abci "github.com/cometbft/cometbft/abci/types" + capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper" capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" feetypes "github.com/cosmos/ibc-go/v8/modules/apps/29-fee/types" channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" - porttypes "github.com/cosmos/ibc-go/v8/modules/core/05-port/types" - host "github.com/cosmos/ibc-go/v8/modules/core/24-host" "github.com/cosmos/ibc-go/v8/modules/core/exported" ) @@ -56,113 +43,39 @@ var ( TestValue = []byte("test-value") ) -var ( - _ module.AppModuleBasic = (*AppModuleBasic)(nil) - _ appmodule.AppModule = (*AppModule)(nil) - - _ porttypes.IBCModule = (*IBCModule)(nil) -) - -// Expected Interface -// PortKeeper defines the expected IBC port keeper +// PortKeeper defines the expected IBC PortKeeper interface. type PortKeeper interface { BindPort(ctx sdk.Context, portID string) *capabilitytypes.Capability IsBound(ctx sdk.Context, portID string) bool } -// AppModuleBasic is the mock AppModuleBasic. -type AppModuleBasic struct{} - -// IsOnePerModuleType implements the depinject.OnePerModuleType interface. -func (AppModuleBasic) IsOnePerModuleType() {} - -// IsAppModule implements the appmodule.AppModule interface. -func (AppModuleBasic) IsAppModule() {} - -// Name implements AppModuleBasic interface. -func (AppModuleBasic) Name() string { - return ModuleName -} - -// IsOnePerModuleType implements the depinject.OnePerModuleType interface. -func (AppModule) IsOnePerModuleType() {} - -// IsAppModule implements the appmodule.AppModule interface. -func (AppModule) IsAppModule() {} - -// RegisterLegacyAminoCodec implements AppModuleBasic interface. -func (AppModuleBasic) RegisterLegacyAminoCodec(*codec.LegacyAmino) {} - -// RegisterInterfaces implements AppModuleBasic interface. -func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) {} - -// DefaultGenesis implements AppModuleBasic interface. -func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { - return nil -} - -// ValidateGenesis implements the AppModuleBasic interface. -func (AppModuleBasic) ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage) error { - return nil -} +// ScopedMockKeeper embeds x/capability's ScopedKeeper used for depinject module outputs. +type ScopedMockKeeper struct{ capabilitykeeper.ScopedKeeper } -// RegisterGRPCGatewayRoutes implements AppModuleBasic interface. -func (AppModuleBasic) RegisterGRPCGatewayRoutes(_ client.Context, _ *runtime.ServeMux) {} +var _ exported.Acknowledgement = (*EmptyAcknowledgement)(nil) -// GetTxCmd implements AppModuleBasic interface. -func (AppModuleBasic) GetTxCmd() *cobra.Command { - return nil +// EmptyAcknowledgement implements the exported.Acknowledgement interface and always returns an empty byte string as Response +type EmptyAcknowledgement struct { + Response []byte } -// GetQueryCmd implements AppModuleBasic interface. -func (AppModuleBasic) GetQueryCmd() *cobra.Command { - return nil -} - -// AppModule represents the AppModule for the mock module. -type AppModule struct { - AppModuleBasic - ibcApps []*IBCApp - portKeeper PortKeeper -} - -// NewAppModule returns a mock AppModule instance. -func NewAppModule(pk PortKeeper) AppModule { - return AppModule{ - portKeeper: pk, +// NewEmptyAcknowledgement returns a new instance of EmptyAcknowledgement +func NewEmptyAcknowledgement() EmptyAcknowledgement { + return EmptyAcknowledgement{ + Response: []byte{}, } } -// RegisterInvariants implements the AppModule interface. -func (AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {} - -// RegisterServices implements the AppModule interface. -func (AppModule) RegisterServices(module.Configurator) {} - -// InitGenesis implements the AppModule interface. -func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate { - for _, ibcApp := range am.ibcApps { - if ibcApp.PortID != "" && !am.portKeeper.IsBound(ctx, ibcApp.PortID) { - // bind mock portID - capability := am.portKeeper.BindPort(ctx, ibcApp.PortID) - err := ibcApp.ScopedKeeper.ClaimCapability(ctx, capability, host.PortPath(ibcApp.PortID)) - if err != nil { - panic(err) - } - } - } - - return []abci.ValidatorUpdate{} +// Success implements the Acknowledgement interface +func (EmptyAcknowledgement) Success() bool { + return true } -// ExportGenesis implements the AppModule interface. -func (AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { - return nil +// Acknowledgement implements the Acknowledgement interface +func (EmptyAcknowledgement) Acknowledgement() []byte { + return []byte{} } -// ConsensusVersion implements AppModule/ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 1 } - var _ exported.Path = KeyPath{} // KeyPath defines a placeholder struct which implements the exported.Path interface diff --git a/testing/mock/module.go b/testing/mock/module.go new file mode 100644 index 00000000000..eee663dec67 --- /dev/null +++ b/testing/mock/module.go @@ -0,0 +1,112 @@ +package mock + +import ( + "encoding/json" + + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + "cosmossdk.io/core/appmodule" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + + abci "github.com/cometbft/cometbft/abci/types" + + host "github.com/cosmos/ibc-go/v8/modules/core/24-host" +) + +var ( + _ module.AppModuleBasic = (*AppModuleBasic)(nil) + _ appmodule.AppModule = (*AppModule)(nil) +) + +// AppModuleBasic is the mock AppModuleBasic. +type AppModuleBasic struct{} + +// IsAppModule implements the appmodule.AppModule interface. +func (AppModuleBasic) IsAppModule() {} + +// Name implements AppModuleBasic interface. +func (AppModuleBasic) Name() string { + return ModuleName +} + +// IsAppModule implements the appmodule.AppModule interface. +func (AppModule) IsAppModule() {} + +// RegisterLegacyAminoCodec implements AppModuleBasic interface. +func (AppModuleBasic) RegisterLegacyAminoCodec(*codec.LegacyAmino) {} + +// RegisterInterfaces implements AppModuleBasic interface. +func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) {} + +// DefaultGenesis implements AppModuleBasic interface. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return nil +} + +// ValidateGenesis implements the AppModuleBasic interface. +func (AppModuleBasic) ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage) error { + return nil +} + +// RegisterGRPCGatewayRoutes implements AppModuleBasic interface. +func (AppModuleBasic) RegisterGRPCGatewayRoutes(_ client.Context, _ *runtime.ServeMux) {} + +// GetTxCmd implements AppModuleBasic interface. +func (AppModuleBasic) GetTxCmd() *cobra.Command { + return nil +} + +// GetQueryCmd implements AppModuleBasic interface. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return nil +} + +// AppModule represents the AppModule for the mock module. +type AppModule struct { + AppModuleBasic + ibcApps []*IBCApp + portKeeper PortKeeper +} + +// NewAppModule returns a mock AppModule instance. +func NewAppModule(pk PortKeeper) AppModule { + return AppModule{ + portKeeper: pk, + } +} + +// RegisterInvariants implements the AppModule interface. +func (AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {} + +// RegisterServices implements the AppModule interface. +func (AppModule) RegisterServices(module.Configurator) {} + +// InitGenesis implements the AppModule interface. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate { + for _, ibcApp := range am.ibcApps { + if ibcApp.PortID != "" && !am.portKeeper.IsBound(ctx, ibcApp.PortID) { + // bind mock portID + capability := am.portKeeper.BindPort(ctx, ibcApp.PortID) + err := ibcApp.ScopedKeeper.ClaimCapability(ctx, capability, host.PortPath(ibcApp.PortID)) + if err != nil { + panic(err) + } + } + } + + return []abci.ValidatorUpdate{} +} + +// ExportGenesis implements the AppModule interface. +func (AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + return nil +} + +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/testing/simapp/abci.go b/testing/simapp/abci.go new file mode 100644 index 00000000000..a6135d9ce9f --- /dev/null +++ b/testing/simapp/abci.go @@ -0,0 +1,84 @@ +package simapp + +import ( + "bytes" + "crypto/rand" + "encoding/json" + "fmt" + + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + + abci "github.com/cometbft/cometbft/abci/types" +) + +type ( + // VoteExtensionHandler defines a dummy vote extension handler for SimApp. + // + // NOTE: This implementation is solely used for testing purposes. DO NOT use + // in a production application! + VoteExtensionHandler struct{} + + // VoteExtension defines the structure used to create a dummy vote extension. + VoteExtension struct { + Hash []byte + Height int64 + Data []byte + } +) + +func NewVoteExtensionHandler() *VoteExtensionHandler { + return &VoteExtensionHandler{} +} + +func (h *VoteExtensionHandler) SetHandlers(bApp *baseapp.BaseApp) { + bApp.SetExtendVoteHandler(h.ExtendVote()) + bApp.SetVerifyVoteExtensionHandler(h.VerifyVoteExtension()) +} + +func (*VoteExtensionHandler) ExtendVote() sdk.ExtendVoteHandler { + return func(_ sdk.Context, req *abci.RequestExtendVote) (*abci.ResponseExtendVote, error) { + buf := make([]byte, 1024) + + _, err := rand.Read(buf) + if err != nil { + return nil, fmt.Errorf("failed to generate random vote extension data: %w", err) + } + + ve := VoteExtension{ + Hash: req.Hash, + Height: req.Height, + Data: buf, + } + + bz, err := json.Marshal(ve) + if err != nil { + return nil, fmt.Errorf("failed to encode vote extension: %w", err) + } + + return &abci.ResponseExtendVote{VoteExtension: bz}, nil + } +} + +func (*VoteExtensionHandler) VerifyVoteExtension() sdk.VerifyVoteExtensionHandler { + return func(ctx sdk.Context, req *abci.RequestVerifyVoteExtension) (*abci.ResponseVerifyVoteExtension, error) { + var ve VoteExtension + + if err := json.Unmarshal(req.VoteExtension, &ve); err != nil { + return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, nil + } + + switch { + case req.Height != ve.Height: + return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, nil + + case !bytes.Equal(req.Hash, ve.Hash): + return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, nil + + case len(ve.Data) != 1024: + return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, nil + } + + return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_ACCEPT}, nil + } +} diff --git a/testing/simapp/app.go b/testing/simapp/app.go index 4a8acb976d0..df910594b08 100644 --- a/testing/simapp/app.go +++ b/testing/simapp/app.go @@ -1,3 +1,5 @@ +//go:build !app_v2 + package simapp import ( diff --git a/testing/simapp/app_config.go b/testing/simapp/app_config.go new file mode 100644 index 00000000000..9b99625cb57 --- /dev/null +++ b/testing/simapp/app_config.go @@ -0,0 +1,325 @@ +package simapp + +import ( + "time" + + "google.golang.org/protobuf/types/known/durationpb" + + _ "cosmossdk.io/x/circuit" // import for side-effects + _ "cosmossdk.io/x/evidence" // import for side-effects + _ "cosmossdk.io/x/feegrant/module" // import for side-effects + _ "cosmossdk.io/x/upgrade" // import for side-effects + _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import for side-effects + _ "github.com/cosmos/cosmos-sdk/x/auth/vesting" // import for side-effects + _ "github.com/cosmos/cosmos-sdk/x/authz/module" // import for side-effects + _ "github.com/cosmos/cosmos-sdk/x/bank" // import for side-effects + _ "github.com/cosmos/cosmos-sdk/x/consensus" // import for side-effects + _ "github.com/cosmos/cosmos-sdk/x/crisis" // import for side-effects + _ "github.com/cosmos/cosmos-sdk/x/distribution" // import for side-effects + _ "github.com/cosmos/cosmos-sdk/x/group/module" // import for side-effects + _ "github.com/cosmos/cosmos-sdk/x/mint" // import for side-effects + _ "github.com/cosmos/cosmos-sdk/x/params" // import for side-effects + _ "github.com/cosmos/cosmos-sdk/x/slashing" // import for side-effects + _ "github.com/cosmos/cosmos-sdk/x/staking" // import for side-effects + _ "github.com/cosmos/ibc-go/modules/capability" // import for side-effects + _ "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts" // import for side-effects + _ "github.com/cosmos/ibc-go/v8/modules/apps/transfer" // import for side-effects + _ "github.com/cosmos/ibc-go/v8/modules/core" // import for side-effects + + runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1" + appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1" + authmodulev1 "cosmossdk.io/api/cosmos/auth/module/v1" + authzmodulev1 "cosmossdk.io/api/cosmos/authz/module/v1" + bankmodulev1 "cosmossdk.io/api/cosmos/bank/module/v1" + circuitmodulev1 "cosmossdk.io/api/cosmos/circuit/module/v1" + consensusmodulev1 "cosmossdk.io/api/cosmos/consensus/module/v1" + crisismodulev1 "cosmossdk.io/api/cosmos/crisis/module/v1" + distrmodulev1 "cosmossdk.io/api/cosmos/distribution/module/v1" + evidencemodulev1 "cosmossdk.io/api/cosmos/evidence/module/v1" + feegrantmodulev1 "cosmossdk.io/api/cosmos/feegrant/module/v1" + genutilmodulev1 "cosmossdk.io/api/cosmos/genutil/module/v1" + govmodulev1 "cosmossdk.io/api/cosmos/gov/module/v1" + groupmodulev1 "cosmossdk.io/api/cosmos/group/module/v1" + mintmodulev1 "cosmossdk.io/api/cosmos/mint/module/v1" + paramsmodulev1 "cosmossdk.io/api/cosmos/params/module/v1" + slashingmodulev1 "cosmossdk.io/api/cosmos/slashing/module/v1" + stakingmodulev1 "cosmossdk.io/api/cosmos/staking/module/v1" + txconfigv1 "cosmossdk.io/api/cosmos/tx/config/v1" + upgrademodulev1 "cosmossdk.io/api/cosmos/upgrade/module/v1" + vestingmodulev1 "cosmossdk.io/api/cosmos/vesting/module/v1" + "cosmossdk.io/core/appconfig" + "cosmossdk.io/depinject" + circuittypes "cosmossdk.io/x/circuit/types" + evidencetypes "cosmossdk.io/x/evidence/types" + "cosmossdk.io/x/feegrant" + upgradetypes "cosmossdk.io/x/upgrade/types" + + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/types/module" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + "github.com/cosmos/cosmos-sdk/x/authz" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + consensustypes "github.com/cosmos/cosmos-sdk/x/consensus/types" + crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" + distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + "github.com/cosmos/cosmos-sdk/x/genutil" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + "github.com/cosmos/cosmos-sdk/x/gov" + govclient "github.com/cosmos/cosmos-sdk/x/gov/client" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/cosmos/cosmos-sdk/x/group" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + paramsclient "github.com/cosmos/cosmos-sdk/x/params/client" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + capabilitymodulev1 "github.com/cosmos/ibc-go/api/capability/module/v1" + icamodulev1 "github.com/cosmos/ibc-go/api/ibc/applications/interchain_accounts/module/v1" + ibctransfermodulev1 "github.com/cosmos/ibc-go/api/ibc/applications/transfer/module/v1" + ibcmodulev1 "github.com/cosmos/ibc-go/api/ibc/core/module/v1" + solomachinemodulev1 "github.com/cosmos/ibc-go/api/ibc/lightclients/solomachine/module/v1" + ibctmmodulev1 "github.com/cosmos/ibc-go/api/ibc/lightclients/tendermint/module/v1" + ibcmockmodulev1 "github.com/cosmos/ibc-go/api/mock/module/v1" + capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" + icatypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/types" + ibctransfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" + ibcexported "github.com/cosmos/ibc-go/v8/modules/core/exported" + solomachine "github.com/cosmos/ibc-go/v8/modules/light-clients/06-solomachine" + ibctm "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" + ibcmock "github.com/cosmos/ibc-go/v8/testing/mock" +) + +var ( + // module account permissions + moduleAccPerms = []*authmodulev1.ModuleAccountPermission{ + {Account: authtypes.FeeCollectorName}, + {Account: distrtypes.ModuleName}, + {Account: minttypes.ModuleName, Permissions: []string{authtypes.Minter}}, + {Account: stakingtypes.BondedPoolName, Permissions: []string{authtypes.Burner, stakingtypes.ModuleName}}, + {Account: stakingtypes.NotBondedPoolName, Permissions: []string{authtypes.Burner, stakingtypes.ModuleName}}, + {Account: govtypes.ModuleName, Permissions: []string{authtypes.Burner}}, + {Account: ibctransfertypes.ModuleName, Permissions: []string{authtypes.Minter, authtypes.Burner}}, + {Account: icatypes.ModuleName}, + } + + // blocked account addresses + blockAccAddrs = []string{ + authtypes.FeeCollectorName, + distrtypes.ModuleName, + minttypes.ModuleName, + stakingtypes.BondedPoolName, + stakingtypes.NotBondedPoolName, + // We allow the following module accounts to receive funds: + // govtypes.ModuleName + } + + // application configuration (used by depinject) + AppConfig = depinject.Configs(appconfig.Compose(&appv1alpha1.Config{ + Modules: []*appv1alpha1.ModuleConfig{ + { + Name: runtime.ModuleName, + Config: appconfig.WrapAny(&runtimev1alpha1.Module{ + AppName: "SimApp", + // NOTE: upgrade module is required to be prioritized + PreBlockers: []string{ + upgradetypes.ModuleName, + }, + // During begin block slashing happens after distr.BeginBlocker so that + // there is nothing left over in the validator fee pool, so as to keep the + // CanWithdrawInvariant invariant. + // NOTE: staking module is required if HistoricalEntries param > 0 + BeginBlockers: []string{ + capabilitytypes.ModuleName, + minttypes.ModuleName, + distrtypes.ModuleName, + slashingtypes.ModuleName, + evidencetypes.ModuleName, + stakingtypes.ModuleName, + authz.ModuleName, + ibcexported.ModuleName, + }, + EndBlockers: []string{ + capabilitytypes.ModuleName, + crisistypes.ModuleName, + govtypes.ModuleName, + stakingtypes.ModuleName, + feegrant.ModuleName, + group.ModuleName, + ibcexported.ModuleName, + }, + OverrideStoreKeys: []*runtimev1alpha1.StoreKeyConfig{ + { + ModuleName: authtypes.ModuleName, + KvStoreKey: "acc", + }, + }, + // NOTE: The genutils module must occur after staking so that pools are + // properly initialized with tokens from genesis accounts. + // NOTE: The genutils module must also occur after auth so that it can access the params from auth. + InitGenesis: []string{ + authtypes.ModuleName, + banktypes.ModuleName, + distrtypes.ModuleName, + stakingtypes.ModuleName, + capabilitytypes.ModuleName, + slashingtypes.ModuleName, + govtypes.ModuleName, + minttypes.ModuleName, + crisistypes.ModuleName, + genutiltypes.ModuleName, + evidencetypes.ModuleName, + authz.ModuleName, + feegrant.ModuleName, + group.ModuleName, + paramstypes.ModuleName, + upgradetypes.ModuleName, + vestingtypes.ModuleName, + circuittypes.ModuleName, + ibcexported.ModuleName, + ibcmock.ModuleName, + ibctransfertypes.ModuleName, + icatypes.ModuleName, + }, + // When ExportGenesis is not specified, the export genesis module order + // is equal to the init genesis order + // ExportGenesis: []string{}, + // Uncomment if you want to set a custom migration order here. + // OrderMigrations: []string{}, + }), + }, + { + Name: authtypes.ModuleName, + Config: appconfig.WrapAny(&authmodulev1.Module{ + Bech32Prefix: "cosmos", + ModuleAccountPermissions: moduleAccPerms, + // By default modules authority is the governance module. This is configurable with the following: + // Authority: "group", // A custom module authority can be set using a module name + // Authority: "cosmos1cwwv22j5ca08ggdv9c2uky355k908694z577tv", // or a specific address + }), + }, + { + Name: vestingtypes.ModuleName, + Config: appconfig.WrapAny(&vestingmodulev1.Module{}), + }, + { + Name: banktypes.ModuleName, + Config: appconfig.WrapAny(&bankmodulev1.Module{ + BlockedModuleAccountsOverride: blockAccAddrs, + }), + }, + { + Name: stakingtypes.ModuleName, + Config: appconfig.WrapAny(&stakingmodulev1.Module{ + // NOTE: specifying a prefix is only necessary when using bech32 addresses + // If not specfied, the auth Bech32Prefix appended with "valoper" and "valcons" is used by default + Bech32PrefixValidator: "cosmosvaloper", + Bech32PrefixConsensus: "cosmosvalcons", + }), + }, + { + Name: slashingtypes.ModuleName, + Config: appconfig.WrapAny(&slashingmodulev1.Module{}), + }, + { + Name: paramstypes.ModuleName, + Config: appconfig.WrapAny(¶msmodulev1.Module{}), + }, + { + Name: "tx", + Config: appconfig.WrapAny(&txconfigv1.Config{}), + }, + { + Name: genutiltypes.ModuleName, + Config: appconfig.WrapAny(&genutilmodulev1.Module{}), + }, + { + Name: authz.ModuleName, + Config: appconfig.WrapAny(&authzmodulev1.Module{}), + }, + { + Name: upgradetypes.ModuleName, + Config: appconfig.WrapAny(&upgrademodulev1.Module{}), + }, + { + Name: distrtypes.ModuleName, + Config: appconfig.WrapAny(&distrmodulev1.Module{}), + }, + { + Name: evidencetypes.ModuleName, + Config: appconfig.WrapAny(&evidencemodulev1.Module{}), + }, + { + Name: minttypes.ModuleName, + Config: appconfig.WrapAny(&mintmodulev1.Module{}), + }, + { + Name: group.ModuleName, + Config: appconfig.WrapAny(&groupmodulev1.Module{ + MaxExecutionPeriod: durationpb.New(time.Second * 1209600), + MaxMetadataLen: 255, + }), + }, + { + Name: feegrant.ModuleName, + Config: appconfig.WrapAny(&feegrantmodulev1.Module{}), + }, + { + Name: govtypes.ModuleName, + Config: appconfig.WrapAny(&govmodulev1.Module{}), + }, + { + Name: crisistypes.ModuleName, + Config: appconfig.WrapAny(&crisismodulev1.Module{}), + }, + { + Name: consensustypes.ModuleName, + Config: appconfig.WrapAny(&consensusmodulev1.Module{}), + }, + { + Name: circuittypes.ModuleName, + Config: appconfig.WrapAny(&circuitmodulev1.Module{}), + }, + { + Name: capabilitytypes.ModuleName, + Config: appconfig.WrapAny(&capabilitymodulev1.Module{SealKeeper: false}), + }, + { + Name: ibcexported.ModuleName, + Config: appconfig.WrapAny(&ibcmodulev1.Module{}), + }, + { + Name: ibctm.ModuleName, + Config: appconfig.WrapAny(&ibctmmodulev1.Module{}), + }, + { + Name: solomachine.ModuleName, + Config: appconfig.WrapAny(&solomachinemodulev1.Module{}), + }, + { + Name: ibcmock.ModuleName, + Config: appconfig.WrapAny(&ibcmockmodulev1.Module{}), + }, + { + Name: ibctransfertypes.ModuleName, + Config: appconfig.WrapAny(&ibctransfermodulev1.Module{}), + }, + { + Name: icatypes.ModuleName, + Config: appconfig.WrapAny(&icamodulev1.Module{}), + }, + }, + }), + depinject.Supply( + // supply custom module basics + map[string]module.AppModuleBasic{ + genutiltypes.ModuleName: genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator), + govtypes.ModuleName: gov.NewAppModuleBasic( + []govclient.ProposalHandler{ + paramsclient.ProposalHandler, + }, + ), + }, + )) +) diff --git a/testing/simapp/app_v2.go b/testing/simapp/app_v2.go new file mode 100644 index 00000000000..68c51c18935 --- /dev/null +++ b/testing/simapp/app_v2.go @@ -0,0 +1,470 @@ +//go:build app_v2 + +package simapp + +import ( + "io" + "os" + "path/filepath" + + dbm "github.com/cosmos/cosmos-db" + + "cosmossdk.io/depinject" + "cosmossdk.io/log" + storetypes "cosmossdk.io/store/types" + circuitkeeper "cosmossdk.io/x/circuit/keeper" + evidencekeeper "cosmossdk.io/x/evidence/keeper" + feegrantkeeper "cosmossdk.io/x/feegrant/keeper" + upgradekeeper "cosmossdk.io/x/upgrade/keeper" + + "github.com/cosmos/cosmos-sdk/baseapp" + "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/server" + "github.com/cosmos/cosmos-sdk/server/api" + "github.com/cosmos/cosmos-sdk/server/config" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + testdata_pulsar "github.com/cosmos/cosmos-sdk/testutil/testdata/testpb" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/auth/ante" + 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" + authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + consensuskeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper" + crisiskeeper "github.com/cosmos/cosmos-sdk/x/crisis/keeper" + distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" + groupkeeper "github.com/cosmos/cosmos-sdk/x/group/keeper" + mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" + paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + + capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper" + icacontrollerkeeper "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/controller/keeper" + icahostkeeper "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/host/keeper" + ibcfeekeeper "github.com/cosmos/ibc-go/v8/modules/apps/29-fee/keeper" + ibctransferkeeper "github.com/cosmos/ibc-go/v8/modules/apps/transfer/keeper" + ibctransfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" + ibckeeper "github.com/cosmos/ibc-go/v8/modules/core/keeper" + ibctypes "github.com/cosmos/ibc-go/v8/modules/core/types" + ibcmock "github.com/cosmos/ibc-go/v8/testing/mock" + ibctestingtypes "github.com/cosmos/ibc-go/v8/testing/types" +) + +// DefaultNodeHome default home directories for the application daemon +var DefaultNodeHome string + +var ( + _ runtime.AppI = (*SimApp)(nil) + _ servertypes.Application = (*SimApp)(nil) +) + +// SimApp extends an ABCI application, but with most of its parameters exported. +// They are exported for convenience in creating helper functions, as object +// capabilities aren't needed for testing. +type SimApp struct { + *runtime.App + legacyAmino *codec.LegacyAmino + appCodec codec.Codec + txConfig client.TxConfig + interfaceRegistry codectypes.InterfaceRegistry + + // keepers + AccountKeeper authkeeper.AccountKeeper + BankKeeper bankkeeper.Keeper + StakingKeeper *stakingkeeper.Keeper + SlashingKeeper slashingkeeper.Keeper + MintKeeper mintkeeper.Keeper + DistrKeeper distrkeeper.Keeper + GovKeeper *govkeeper.Keeper + CrisisKeeper *crisiskeeper.Keeper + UpgradeKeeper *upgradekeeper.Keeper + ParamsKeeper paramskeeper.Keeper + AuthzKeeper authzkeeper.Keeper + EvidenceKeeper evidencekeeper.Keeper + FeeGrantKeeper feegrantkeeper.Keeper + GroupKeeper groupkeeper.Keeper + ConsensusParamsKeeper consensuskeeper.Keeper + CircuitBreakerKeeper circuitkeeper.Keeper + + CapabilityKeeper *capabilitykeeper.Keeper + ScopedIBCKeeper ibctypes.ScopedIBCKeeper + ScopedIBCMockKeeper ibcmock.ScopedMockKeeper + ScopedTransferKeeper ibctransfertypes.ScopedTransferKeeper + ScopedFeeMockKeeper capabilitykeeper.ScopedKeeper + ScopedICAControllerKeeper capabilitykeeper.ScopedKeeper + ScopedICAHostKeeper capabilitykeeper.ScopedKeeper + ScopedICAMockKeeper capabilitykeeper.ScopedKeeper + + IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly + + IBCFeeKeeper ibcfeekeeper.Keeper + ICAControllerKeeper icacontrollerkeeper.Keeper + ICAHostKeeper icahostkeeper.Keeper + TransferKeeper ibctransferkeeper.Keeper + + // make IBC modules public for test purposes + // these modules are never directly routed to by the IBC Router + IBCMockModule ibcmock.IBCModule + ICAAuthModule ibcmock.IBCModule + FeeMockModule ibcmock.IBCModule + + // simulation manager + sm *module.SimulationManager +} + +func init() { + userHomeDir, err := os.UserHomeDir() + if err != nil { + panic(err) + } + + DefaultNodeHome = filepath.Join(userHomeDir, ".simapp") +} + +// NewSimApp returns a reference to an initialized SimApp. +func NewSimApp( + logger log.Logger, + db dbm.DB, + traceStore io.Writer, + loadLatest bool, + appOpts servertypes.AppOptions, + baseAppOptions ...func(*baseapp.BaseApp), +) *SimApp { + var ( + app = &SimApp{} + appBuilder *runtime.AppBuilder + + // merge the AppConfig and other configuration in one config + appConfig = depinject.Configs( + AppConfig, + depinject.Supply( + // supply the application options + appOpts, + // supply the logger + logger, + + // ADVANCED CONFIGURATION + + // + // AUTH + // + // For providing a custom function required in auth to generate custom account types + // add it below. By default the auth module uses simulation.RandomGenesisAccounts. + // + // authtypes.RandomGenesisAccountsFn(simulation.RandomGenesisAccounts), + // + // For providing a custom a base account type add it below. + // By default the auth module uses authtypes.ProtoBaseAccount(). + // + // func() sdk.AccountI { return authtypes.ProtoBaseAccount() }, + // + // For providing a different address codec, add it below. + // By default the auth module uses a Bech32 address codec, + // with the prefix defined in the auth module configuration. + // + // func() address.Codec { return <- custom address codec type -> } + + // + // STAKING + // + // For provinding a different validator and consensus address codec, add it below. + // By default the staking module uses the bech32 prefix provided in the auth config, + // and appends "valoper" and "valcons" for validator and consensus addresses respectively. + // When providing a custom address codec in auth, custom address codecs must be provided here as well. + // + // func() runtime.ValidatorAddressCodec { return <- custom validator address codec type -> } + // func() runtime.ConsensusAddressCodec { return <- custom consensus address codec type -> } + + // + // MINT + // + + // For providing a custom inflation function for x/mint add here your + // custom function that implements the minttypes.InflationCalculationFn + // interface. + ), + ) + ) + + if err := depinject.Inject(appConfig, + &appBuilder, + &app.appCodec, + &app.legacyAmino, + &app.txConfig, + &app.interfaceRegistry, + &app.AccountKeeper, + &app.BankKeeper, + &app.StakingKeeper, + &app.SlashingKeeper, + &app.MintKeeper, + &app.DistrKeeper, + &app.GovKeeper, + &app.CrisisKeeper, + &app.UpgradeKeeper, + &app.ParamsKeeper, + &app.AuthzKeeper, + &app.EvidenceKeeper, + &app.FeeGrantKeeper, + &app.GroupKeeper, + &app.ConsensusParamsKeeper, + &app.CircuitBreakerKeeper, + &app.CapabilityKeeper, + &app.IBCKeeper, + &app.ScopedIBCKeeper, + &app.IBCMockModule, + &app.ScopedIBCMockKeeper, + &app.TransferKeeper, + &app.ScopedTransferKeeper, + ); err != nil { + panic(err) + } + + // Below we could construct and set an application specific mempool and + // ABCI 1.0 PrepareProposal and ProcessProposal handlers. These defaults are + // already set in the SDK's BaseApp, this shows an example of how to override + // them. + // + // Example: + // + // app.App = appBuilder.Build(...) + // nonceMempool := mempool.NewSenderNonceMempool() + // abciPropHandler := NewDefaultProposalHandler(nonceMempool, app.App.BaseApp) + // + // app.App.BaseApp.SetMempool(nonceMempool) + // app.App.BaseApp.SetPrepareProposal(abciPropHandler.PrepareProposalHandler()) + // app.App.BaseApp.SetProcessProposal(abciPropHandler.ProcessProposalHandler()) + // + // Alternatively, you can construct BaseApp options, append those to + // baseAppOptions and pass them to the appBuilder. + // + // Example: + // + // prepareOpt = func(app *baseapp.BaseApp) { + // abciPropHandler := baseapp.NewDefaultProposalHandler(nonceMempool, app) + // app.SetPrepareProposal(abciPropHandler.PrepareProposalHandler()) + // } + // baseAppOptions = append(baseAppOptions, prepareOpt) + + // create and set dummy vote extension handler + voteExtOp := func(bApp *baseapp.BaseApp) { + voteExtHandler := NewVoteExtensionHandler() + voteExtHandler.SetHandlers(bApp) + } + baseAppOptions = append(baseAppOptions, voteExtOp, baseapp.SetOptimisticExecution()) + + app.App = appBuilder.Build(db, traceStore, baseAppOptions...) + + // register streaming services + if err := app.RegisterStreamingServices(appOpts, app.kvStoreKeys()); err != nil { + panic(err) + } + + app.setAnteHandler(app.GetTxConfig()) + + // === Module Options === + app.ModuleManager.RegisterInvariants(app.CrisisKeeper) + + // RegisterUpgradeHandlers is used for registering any on-chain upgrades. + app.registerUpgradeHandlers() + + // add test gRPC service for testing gRPC queries in isolation + testdata_pulsar.RegisterQueryServer(app.GRPCQueryRouter(), testdata_pulsar.QueryImpl{}) + + // create the simulation manager and define the order of the modules for deterministic simulations + // + // NOTE: this is not required apps that don't use the simulator for fuzz testing + // transactions + overrideModules := map[string]module.AppModuleSimulation{ + authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)), + } + app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, overrideModules) + + app.sm.RegisterStoreDecoders() + + // A custom InitChainer can be set if extra pre-init-genesis logic is required. + // By default, when using app wiring enabled module, this is not required. + // For instance, the upgrade module will set automatically the module version map in its init genesis thanks to app wiring. + // However, when registering a module manually (i.e. that does not support app wiring), the module version map + // must be set manually as follow. The upgrade module will de-duplicate the module version map. + // + // app.SetInitChainer(func(ctx sdk.Context, req *abci.RequestInitChain) (*abci.ResponseInitChain, error) { + // app.UpgradeKeeper.SetModuleVersionMap(ctx, app.ModuleManager.GetVersionMap()) + // return app.App.InitChainer(ctx, req) + // }) + + if err := app.Load(loadLatest); err != nil { + panic(err) + } + + return app +} + +func (app *SimApp) setAnteHandler(txConfig client.TxConfig) { + anteHandler, err := NewAnteHandler( + HandlerOptions{ + ante.HandlerOptions{ + AccountKeeper: app.AccountKeeper, + BankKeeper: app.BankKeeper, + SignModeHandler: txConfig.SignModeHandler(), + FeegrantKeeper: app.FeeGrantKeeper, + SigGasConsumer: ante.DefaultSigVerificationGasConsumer, + }, + &app.CircuitBreakerKeeper, + app.IBCKeeper, + }, + ) + if err != nil { + panic(err) + } + + // Set the AnteHandler for the app + app.SetAnteHandler(anteHandler) +} + +// LegacyAmino returns SimApp's amino codec. +// +// NOTE: This is solely to be used for testing purposes as it may be desirable +// for modules to register their own custom testing types. +func (app *SimApp) LegacyAmino() *codec.LegacyAmino { + return app.legacyAmino +} + +// AppCodec returns SimApp's app codec. +// +// NOTE: This is solely to be used for testing purposes as it may be desirable +// for modules to register their own custom testing types. +func (app *SimApp) AppCodec() codec.Codec { + return app.appCodec +} + +// InterfaceRegistry returns SimApp's InterfaceRegistry. +func (app *SimApp) InterfaceRegistry() codectypes.InterfaceRegistry { + return app.interfaceRegistry +} + +// TxConfig returns SimApp's TxConfig +func (app *SimApp) TxConfig() client.TxConfig { + return app.txConfig +} + +// GetKey returns the KVStoreKey for the provided store key. +// +// NOTE: This is solely to be used for testing purposes. +func (app *SimApp) GetKey(storeKey string) *storetypes.KVStoreKey { + sk := app.UnsafeFindStoreKey(storeKey) + kvStoreKey, ok := sk.(*storetypes.KVStoreKey) + if !ok { + return nil + } + return kvStoreKey +} + +func (app *SimApp) kvStoreKeys() map[string]*storetypes.KVStoreKey { + keys := make(map[string]*storetypes.KVStoreKey) + for _, k := range app.GetStoreKeys() { + if kv, ok := k.(*storetypes.KVStoreKey); ok { + keys[kv.Name()] = kv + } + } + + return keys +} + +// GetSubspace returns a param subspace for a given module name. +// +// NOTE: This is solely to be used for testing purposes. +func (app *SimApp) GetSubspace(moduleName string) paramstypes.Subspace { + subspace, _ := app.ParamsKeeper.GetSubspace(moduleName) + return subspace +} + +// SimulationManager implements the SimulationApp interface +func (app *SimApp) SimulationManager() *module.SimulationManager { + return app.sm +} + +// RegisterAPIRoutes registers all application module routes with the provided +// API server. +func (app *SimApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) { + app.App.RegisterAPIRoutes(apiSvr, apiConfig) + // register swagger API in app.go so that other applications can override easily + if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil { + panic(err) + } +} + +// GetMaccPerms returns a copy of the module account permissions +// +// NOTE: This is solely to be used for testing purposes. +func GetMaccPerms() map[string][]string { + dup := make(map[string][]string) + for _, perms := range moduleAccPerms { + dup[perms.Account] = perms.Permissions + } + + return dup +} + +// BlockedAddresses returns all the app's blocked account addresses. +func BlockedAddresses() map[string]bool { + result := make(map[string]bool) + + if len(blockAccAddrs) > 0 { + for _, addr := range blockAccAddrs { + result[addr] = true + } + } else { + for addr := range GetMaccPerms() { + result[addr] = true + } + } + + return result +} + +// IBC TestingApp functions + +// GetBaseApp implements the TestingApp interface. +func (app *SimApp) GetBaseApp() *baseapp.BaseApp { + return app.BaseApp +} + +// GetStakingKeeper implements the TestingApp interface. +func (app *SimApp) GetStakingKeeper() ibctestingtypes.StakingKeeper { + return app.StakingKeeper +} + +// GetIBCKeeper implements the TestingApp interface. +func (app *SimApp) GetIBCKeeper() *ibckeeper.Keeper { + return app.IBCKeeper +} + +// GetScopedIBCKeeper implements the TestingApp interface. +func (app *SimApp) GetScopedIBCKeeper() capabilitykeeper.ScopedKeeper { + return app.ScopedIBCKeeper.ScopedKeeper +} + +// GetTxConfig implements the TestingApp interface. +func (app *SimApp) GetTxConfig() client.TxConfig { + return app.txConfig +} + +// GetMemKey returns the MemStoreKey for the provided mem key. +// +// NOTE: This is solely used for testing purposes. +func (app *SimApp) GetMemKey(storeKey string) *storetypes.MemoryStoreKey { + sk := app.UnsafeFindStoreKey(storeKey) + memStoreKey, ok := sk.(*storetypes.MemoryStoreKey) + if !ok { + return nil + } + return memStoreKey +} diff --git a/testing/simapp/export.go b/testing/simapp/export.go index 26438874ac8..df3715c1c18 100644 --- a/testing/simapp/export.go +++ b/testing/simapp/export.go @@ -202,7 +202,7 @@ func (app *SimApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs [] // Iterate through validators by power descending, reset bond heights, and // update bond intra-tx counters. - store := ctx.KVStore(app.keys[stakingtypes.StoreKey]) + store := ctx.KVStore(app.GetKey(stakingtypes.StoreKey)) iter := storetypes.KVStoreReversePrefixIterator(store, stakingtypes.ValidatorsKey) counter := int16(0) diff --git a/testing/simapp/simd/cmd/commands.go b/testing/simapp/simd/cmd/commands.go new file mode 100644 index 00000000000..8144b51a37c --- /dev/null +++ b/testing/simapp/simd/cmd/commands.go @@ -0,0 +1,245 @@ +package cmd + +import ( + "errors" + "io" + + dbm "github.com/cosmos/cosmos-db" + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "cosmossdk.io/log" + confixcmd "cosmossdk.io/tools/confix/cmd" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/debug" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/keys" + "github.com/cosmos/cosmos-sdk/client/pruning" + "github.com/cosmos/cosmos-sdk/client/rpc" + "github.com/cosmos/cosmos-sdk/client/snapshot" + "github.com/cosmos/cosmos-sdk/server" + serverconfig "github.com/cosmos/cosmos-sdk/server/config" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" + "github.com/cosmos/cosmos-sdk/x/crisis" + genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" + + cmtcfg "github.com/cometbft/cometbft/config" + + "github.com/cosmos/ibc-go/v8/testing/simapp" +) + +// initCometBFTConfig helps to override default CometBFT Config values. +// return cmtcfg.DefaultConfig if no custom configuration is required for the application. +func initCometBFTConfig() *cmtcfg.Config { + cfg := cmtcfg.DefaultConfig() + + // these values put a higher strain on node memory + // cfg.P2P.MaxNumInboundPeers = 100 + // cfg.P2P.MaxNumOutboundPeers = 40 + + return cfg +} + +// initAppConfig helps to override default appConfig template and configs. +// return "", nil if no custom configuration is required for the application. +func initAppConfig() (string, interface{}) { + // The following code snippet is just for reference. + + // WASMConfig defines configuration for the wasm module. + type WASMConfig struct { + // This is the maximum sdk gas (wasm and storage) that we allow for any x/wasm "smart" queries + QueryGasLimit uint64 `mapstructure:"query_gas_limit"` + + // Address defines the gRPC-web server to listen on + LruSize uint64 `mapstructure:"lru_size"` + } + + type CustomAppConfig struct { + serverconfig.Config + + WASM WASMConfig `mapstructure:"wasm"` + } + + // Optionally allow the chain developer to overwrite the SDK's default + // server config. + srvCfg := serverconfig.DefaultConfig() + // The SDK's default minimum gas price is set to "" (empty value) inside + // app.toml. If left empty by validators, the node will halt on startup. + // However, the chain developer can set a default app.toml value for their + // validators here. + // + // In summary: + // - if you leave srvCfg.MinGasPrices = "", all validators MUST tweak their + // own app.toml config, + // - if you set srvCfg.MinGasPrices non-empty, validators CAN tweak their + // own app.toml to override, or use this default value. + // + // In simapp, we set the min gas prices to 0. + srvCfg.MinGasPrices = "0stake" + // srvCfg.BaseConfig.IAVLDisableFastNode = true // disable fastnode by default + + customAppConfig := CustomAppConfig{ + Config: *srvCfg, + WASM: WASMConfig{ + LruSize: 1, + QueryGasLimit: 300000, + }, + } + + customAppTemplate := serverconfig.DefaultConfigTemplate + ` +[wasm] +# This is the maximum sdk gas (wasm and storage) that we allow for any x/wasm "smart" queries +query_gas_limit = 300000 +# This is the number of wasm vm instances we keep cached in memory for speed-up +# Warning: this is currently unstable and may lead to crashes, best to keep for 0 unless testing locally +lru_size = 0` + + return customAppTemplate, customAppConfig +} + +func initRootCmd(rootCmd *cobra.Command, txConfig client.TxConfig, basicManager module.BasicManager) { + cfg := sdk.GetConfig() + cfg.Seal() + + rootCmd.AddCommand( + genutilcli.InitCmd(basicManager, simapp.DefaultNodeHome), + debug.Cmd(), + confixcmd.ConfigCommand(), + pruning.Cmd(newApp, simapp.DefaultNodeHome), + snapshot.Cmd(newApp), + server.QueryBlockResultsCmd(), + ) + + server.AddCommands(rootCmd, simapp.DefaultNodeHome, newApp, appExport, addModuleInitFlags) + + // add keybase, auxiliary RPC, query, genesis, and tx child commands + rootCmd.AddCommand( + server.StatusCommand(), + genesisCommand(txConfig, basicManager), + txCommand(), + queryCommand(), + keys.Commands(), + ) +} + +func addModuleInitFlags(startCmd *cobra.Command) { + crisis.AddModuleInitFlags(startCmd) +} + +func queryCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "query", + Aliases: []string{"q"}, + Short: "Querying subcommands", + DisableFlagParsing: false, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + cmd.AddCommand( + rpc.ValidatorCommand(), + server.QueryBlockCmd(), + authcmd.QueryTxsByEventsCmd(), + server.QueryBlocksCmd(), + authcmd.QueryTxCmd(), + authcmd.GetSimulateCmd(), + ) + + return cmd +} + +func txCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "tx", + Short: "Transactions subcommands", + DisableFlagParsing: false, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + cmd.AddCommand( + authcmd.GetSignCommand(), + authcmd.GetSignBatchCommand(), + authcmd.GetMultiSignCommand(), + authcmd.GetMultiSignBatchCmd(), + authcmd.GetValidateSignaturesCommand(), + authcmd.GetBroadcastCommand(), + authcmd.GetEncodeCommand(), + authcmd.GetDecodeCommand(), + authcmd.GetSimulateCmd(), + ) + + return cmd +} + +// genesisCommand builds genesis-related `simd genesis` command. Users may provide application specific commands as a parameter +func genesisCommand(txConfig client.TxConfig, basicManager module.BasicManager, cmds ...*cobra.Command) *cobra.Command { + cmd := genutilcli.Commands(txConfig, basicManager, simapp.DefaultNodeHome) + + for _, subCmd := range cmds { + cmd.AddCommand(subCmd) + } + return cmd +} + +// newApp creates the application +func newApp( + logger log.Logger, + db dbm.DB, + traceStore io.Writer, + appOpts servertypes.AppOptions, +) servertypes.Application { + baseappOptions := server.DefaultBaseappOptions(appOpts) + + return simapp.NewSimApp( + logger, db, traceStore, true, + appOpts, + baseappOptions..., + ) +} + +// appExport creates a new simapp (optionally at a given height) and exports state. +func appExport( + logger log.Logger, + db dbm.DB, + traceStore io.Writer, + height int64, + forZeroHeight bool, + jailAllowedAddrs []string, + appOpts servertypes.AppOptions, + modulesToExport []string, +) (servertypes.ExportedApp, error) { + var simApp *simapp.SimApp + + // this check is necessary as we use the flag in x/upgrade. + // we can exit more gracefully by checking the flag here. + homePath, ok := appOpts.Get(flags.FlagHome).(string) + if !ok || homePath == "" { + return servertypes.ExportedApp{}, errors.New("application home not set") + } + + viperAppOpts, ok := appOpts.(*viper.Viper) + if !ok { + return servertypes.ExportedApp{}, errors.New("appOpts is not viper.Viper") + } + + // overwrite the FlagInvCheckPeriod + viperAppOpts.Set(server.FlagInvCheckPeriod, 1) + appOpts = viperAppOpts + + if height != -1 { + simApp = simapp.NewSimApp(logger, db, traceStore, false, appOpts) + + if err := simApp.LoadHeight(height); err != nil { + return servertypes.ExportedApp{}, err + } + } else { + simApp = simapp.NewSimApp(logger, db, traceStore, true, appOpts) + } + + return simApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs, modulesToExport) +} diff --git a/testing/simapp/simd/cmd/root.go b/testing/simapp/simd/cmd/root.go index 58990794d06..41c2bb43d10 100644 --- a/testing/simapp/simd/cmd/root.go +++ b/testing/simapp/simd/cmd/root.go @@ -1,44 +1,28 @@ +//go:build !app_v2 + package cmd import ( - "errors" - "io" "os" dbm "github.com/cosmos/cosmos-db" "github.com/spf13/cobra" - "github.com/spf13/viper" "cosmossdk.io/client/v2/autocli" "cosmossdk.io/log" - confixcmd "cosmossdk.io/tools/confix/cmd" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/config" - "github.com/cosmos/cosmos-sdk/client/debug" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/keys" - "github.com/cosmos/cosmos-sdk/client/pruning" - "github.com/cosmos/cosmos-sdk/client/rpc" - "github.com/cosmos/cosmos-sdk/client/snapshot" "github.com/cosmos/cosmos-sdk/codec" addresscodec "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/server" - serverconfig "github.com/cosmos/cosmos-sdk/server/config" - 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" "github.com/cosmos/cosmos-sdk/types/tx/signing" - authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" "github.com/cosmos/cosmos-sdk/x/auth/tx" txmodule "github.com/cosmos/cosmos-sdk/x/auth/tx/config" "github.com/cosmos/cosmos-sdk/x/auth/types" - "github.com/cosmos/cosmos-sdk/x/crisis" - genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" - - cmtcfg "github.com/cometbft/cometbft/config" "github.com/cosmos/ibc-go/v8/testing/simapp" "github.com/cosmos/ibc-go/v8/testing/simapp/params" @@ -115,7 +99,7 @@ func NewRootCmd() *cobra.Command { }, } - initRootCmd(rootCmd, encodingConfig, tempApp.BasicModuleManager) + initRootCmd(rootCmd, encodingConfig.TxConfig, tempApp.BasicModuleManager) autoCliOpts, err := enrichAutoCliOpts(tempApp.AutoCliOpts(), initClientCtx) if err != nil { @@ -149,218 +133,6 @@ func enrichAutoCliOpts(autoCliOpts autocli.AppOptions, clientCtx client.Context) return autoCliOpts, nil } -// initCometBFTConfig helps to override default CometBFT Config values. -// return cmtcfg.DefaultConfig if no custom configuration is required for the application. -func initCometBFTConfig() *cmtcfg.Config { - cfg := cmtcfg.DefaultConfig() - - // these values put a higher strain on node memory - // cfg.P2P.MaxNumInboundPeers = 100 - // cfg.P2P.MaxNumOutboundPeers = 40 - - return cfg -} - -// initAppConfig helps to override default appConfig template and configs. -// return "", nil if no custom configuration is required for the application. -func initAppConfig() (string, interface{}) { - // The following code snippet is just for reference. - - // WASMConfig defines configuration for the wasm module. - type WASMConfig struct { - // This is the maximum sdk gas (wasm and storage) that we allow for any x/wasm "smart" queries - QueryGasLimit uint64 `mapstructure:"query_gas_limit"` - - // Address defines the gRPC-web server to listen on - LruSize uint64 `mapstructure:"lru_size"` - } - - type CustomAppConfig struct { - serverconfig.Config - - WASM WASMConfig `mapstructure:"wasm"` - } - - // Optionally allow the chain developer to overwrite the SDK's default - // server config. - srvCfg := serverconfig.DefaultConfig() - // The SDK's default minimum gas price is set to "" (empty value) inside - // app.toml. If left empty by validators, the node will halt on startup. - // However, the chain developer can set a default app.toml value for their - // validators here. - // - // In summary: - // - if you leave srvCfg.MinGasPrices = "", all validators MUST tweak their - // own app.toml config, - // - if you set srvCfg.MinGasPrices non-empty, validators CAN tweak their - // own app.toml to override, or use this default value. - // - // In simapp, we set the min gas prices to 0. - srvCfg.MinGasPrices = "0stake" - // srvCfg.BaseConfig.IAVLDisableFastNode = true // disable fastnode by default - - customAppConfig := CustomAppConfig{ - Config: *srvCfg, - WASM: WASMConfig{ - LruSize: 1, - QueryGasLimit: 300000, - }, - } - - customAppTemplate := serverconfig.DefaultConfigTemplate + ` -[wasm] -# This is the maximum sdk gas (wasm and storage) that we allow for any x/wasm "smart" queries -query_gas_limit = 300000 -# This is the number of wasm vm instances we keep cached in memory for speed-up -# Warning: this is currently unstable and may lead to crashes, best to keep for 0 unless testing locally -lru_size = 0` - - return customAppTemplate, customAppConfig -} - -func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig, basicManager module.BasicManager) { - cfg := sdk.GetConfig() - cfg.Seal() - - rootCmd.AddCommand( - genutilcli.InitCmd(basicManager, simapp.DefaultNodeHome), - debug.Cmd(), - confixcmd.ConfigCommand(), - pruning.Cmd(newApp, simapp.DefaultNodeHome), - snapshot.Cmd(newApp), - server.QueryBlockResultsCmd(), - ) - - server.AddCommands(rootCmd, simapp.DefaultNodeHome, newApp, appExport, addModuleInitFlags) - - // add keybase, auxiliary RPC, query, genesis, and tx child commands - rootCmd.AddCommand( - server.StatusCommand(), - genesisCommand(encodingConfig, basicManager), - txCommand(), - queryCommand(), - keys.Commands(), - ) -} - -func addModuleInitFlags(startCmd *cobra.Command) { - crisis.AddModuleInitFlags(startCmd) -} - -func queryCommand() *cobra.Command { - cmd := &cobra.Command{ - Use: "query", - Aliases: []string{"q"}, - Short: "Querying subcommands", - DisableFlagParsing: false, - SuggestionsMinimumDistance: 2, - RunE: client.ValidateCmd, - } - - cmd.AddCommand( - rpc.ValidatorCommand(), - server.QueryBlockCmd(), - authcmd.QueryTxsByEventsCmd(), - server.QueryBlocksCmd(), - authcmd.QueryTxCmd(), - authcmd.GetSimulateCmd(), - ) - - return cmd -} - -func txCommand() *cobra.Command { - cmd := &cobra.Command{ - Use: "tx", - Short: "Transactions subcommands", - DisableFlagParsing: false, - SuggestionsMinimumDistance: 2, - RunE: client.ValidateCmd, - } - - cmd.AddCommand( - authcmd.GetSignCommand(), - authcmd.GetSignBatchCommand(), - authcmd.GetMultiSignCommand(), - authcmd.GetMultiSignBatchCmd(), - authcmd.GetValidateSignaturesCommand(), - authcmd.GetBroadcastCommand(), - authcmd.GetEncodeCommand(), - authcmd.GetDecodeCommand(), - authcmd.GetSimulateCmd(), - ) - - return cmd -} - -// genesisCommand builds genesis-related `simd genesis` command. Users may provide application specific commands as a parameter -func genesisCommand(encodingConfig params.EncodingConfig, basicManager module.BasicManager, cmds ...*cobra.Command) *cobra.Command { - cmd := genutilcli.Commands(encodingConfig.TxConfig, basicManager, simapp.DefaultNodeHome) - - for _, subCmd := range cmds { - cmd.AddCommand(subCmd) - } - return cmd -} - -// newApp creates the application -func newApp( - logger log.Logger, - db dbm.DB, - traceStore io.Writer, - appOpts servertypes.AppOptions, -) servertypes.Application { - baseappOptions := server.DefaultBaseappOptions(appOpts) - - return simapp.NewSimApp( - logger, db, traceStore, true, - appOpts, - baseappOptions..., - ) -} - -// appExport creates a new simapp (optionally at a given height) and exports state. -func appExport( - logger log.Logger, - db dbm.DB, - traceStore io.Writer, - height int64, - forZeroHeight bool, - jailAllowedAddrs []string, - appOpts servertypes.AppOptions, - modulesToExport []string, -) (servertypes.ExportedApp, error) { - var simApp *simapp.SimApp - - // this check is necessary as we use the flag in x/upgrade. - // we can exit more gracefully by checking the flag here. - homePath, ok := appOpts.Get(flags.FlagHome).(string) - if !ok || homePath == "" { - return servertypes.ExportedApp{}, errors.New("application home not set") - } - - viperAppOpts, ok := appOpts.(*viper.Viper) - if !ok { - return servertypes.ExportedApp{}, errors.New("appOpts is not viper.Viper") - } - - // overwrite the FlagInvCheckPeriod - viperAppOpts.Set(server.FlagInvCheckPeriod, 1) - appOpts = viperAppOpts - - if height != -1 { - simApp = simapp.NewSimApp(logger, db, traceStore, false, appOpts) - - if err := simApp.LoadHeight(height); err != nil { - return servertypes.ExportedApp{}, err - } - } else { - simApp = simapp.NewSimApp(logger, db, traceStore, true, appOpts) - } - - return simApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs, modulesToExport) -} - var tempDir = func() string { dir, err := os.MkdirTemp("", "simapp") if err != nil { diff --git a/testing/simapp/simd/cmd/root_v2.go b/testing/simapp/simd/cmd/root_v2.go new file mode 100644 index 00000000000..3a1a13311e8 --- /dev/null +++ b/testing/simapp/simd/cmd/root_v2.go @@ -0,0 +1,143 @@ +//go:build app_v2 + +package cmd + +import ( + "os" + + "github.com/spf13/cobra" + + "cosmossdk.io/client/v2/autocli" + clientv2keyring "cosmossdk.io/client/v2/autocli/keyring" + "cosmossdk.io/core/address" + "cosmossdk.io/depinject" + "cosmossdk.io/log" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/config" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/server" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/auth/tx" + authtxconfig "github.com/cosmos/cosmos-sdk/x/auth/tx/config" + "github.com/cosmos/cosmos-sdk/x/auth/types" + + "github.com/cosmos/ibc-go/v8/testing/simapp" +) + +var tempDir = func() string { + dir, err := os.MkdirTemp("", "simapp") + if err != nil { + dir = simapp.DefaultNodeHome + } + defer os.RemoveAll(dir) + + return dir +} + +// NewRootCmd creates a new root command for simd. It is called once in the main function. +func NewRootCmd() *cobra.Command { + var ( + autoCliOpts autocli.AppOptions + moduleBasicManager module.BasicManager + clientCtx client.Context + ) + + if err := depinject.Inject( + depinject.Configs(simapp.AppConfig, + depinject.Supply( + log.NewNopLogger(), + simtestutil.NewAppOptionsWithFlagHome(tempDir()), + ), + depinject.Provide( + ProvideClientContext, + ProvideKeyring, + ), + ), + &autoCliOpts, + &moduleBasicManager, + &clientCtx, + ); err != nil { + panic(err) + } + + rootCmd := &cobra.Command{ + Use: "simd", + Short: "simulation app", + SilenceErrors: true, + PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { + // set the default command outputs + cmd.SetOut(cmd.OutOrStdout()) + cmd.SetErr(cmd.ErrOrStderr()) + + clientCtx = clientCtx.WithCmdContext(cmd.Context()).WithViper("") + clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags()) + if err != nil { + return err + } + + clientCtx, err = config.ReadFromClientConfig(clientCtx) + if err != nil { + return err + } + + if err := client.SetCmdClientContextHandler(clientCtx, cmd); err != nil { + return err + } + + customAppTemplate, customAppConfig := initAppConfig() + customCMTConfig := initCometBFTConfig() + + return server.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, customCMTConfig) + }, + } + + initRootCmd(rootCmd, clientCtx.TxConfig, moduleBasicManager) + + if err := autoCliOpts.EnhanceRootCommand(rootCmd); err != nil { + panic(err) + } + + return rootCmd +} + +func ProvideClientContext( + appCodec codec.Codec, + interfaceRegistry codectypes.InterfaceRegistry, + txConfigOpts tx.ConfigOptions, + legacyAmino *codec.LegacyAmino, +) client.Context { + clientCtx := client.Context{}. + WithCodec(appCodec). + WithInterfaceRegistry(interfaceRegistry). + WithLegacyAmino(legacyAmino). + WithInput(os.Stdin). + WithAccountRetriever(types.AccountRetriever{}). + WithHomeDir(simapp.DefaultNodeHome). + WithViper("") // In simapp, we don't use any prefix for env variables. + + // Read the config again to overwrite the default values with the values from the config file + clientCtx, _ = config.ReadDefaultValuesFromDefaultClientConfig(clientCtx) + + // textual is enabled by default, we need to re-create the tx config grpc instead of bank keeper. + txConfigOpts.TextualCoinMetadataQueryFn = authtxconfig.NewGRPCCoinMetadataQueryFn(clientCtx) + txConfig, err := tx.NewTxConfigWithOptions(clientCtx.Codec, txConfigOpts) + if err != nil { + panic(err) + } + clientCtx = clientCtx.WithTxConfig(txConfig) + + return clientCtx +} + +func ProvideKeyring(clientCtx client.Context, addressCodec address.Codec) (clientv2keyring.Keyring, error) { + kb, err := client.NewKeyringFromBackend(clientCtx, clientCtx.Keyring.Backend()) + if err != nil { + return nil, err + } + + return keyring.NewAutoCLIKeyring(kb) +} diff --git a/testing/simapp/upgrades.go b/testing/simapp/upgrades.go index 2c0ddaf1071..29a2d0dc045 100644 --- a/testing/simapp/upgrades.go +++ b/testing/simapp/upgrades.go @@ -18,7 +18,7 @@ import ( func (app *SimApp) registerUpgradeHandlers() { app.UpgradeKeeper.SetUpgradeHandler( upgrades.V5, - upgrades.CreateDefaultUpgradeHandler(app.ModuleManager, app.configurator), + upgrades.CreateDefaultUpgradeHandler(app.ModuleManager, app.Configurator()), ) // NOTE: The moduleName arg of v6.CreateUpgradeHandler refers to the auth module ScopedKeeper name to which the channel capability should be migrated from. @@ -28,9 +28,9 @@ func (app *SimApp) registerUpgradeHandlers() { upgrades.V6, upgrades.CreateV6UpgradeHandler( app.ModuleManager, - app.configurator, + app.Configurator(), app.appCodec, - app.keys[capabilitytypes.ModuleName], + app.GetKey(capabilitytypes.ModuleName), app.CapabilityKeeper, ibcmock.ModuleName+icacontrollertypes.SubModuleName, ), @@ -40,7 +40,7 @@ func (app *SimApp) registerUpgradeHandlers() { upgrades.V7, upgrades.CreateV7UpgradeHandler( app.ModuleManager, - app.configurator, + app.Configurator(), app.appCodec, *app.IBCKeeper.ClientKeeper, app.ConsensusParamsKeeper, @@ -50,14 +50,14 @@ func (app *SimApp) registerUpgradeHandlers() { app.UpgradeKeeper.SetUpgradeHandler( upgrades.V7_1, - upgrades.CreateV7LocalhostUpgradeHandler(app.ModuleManager, app.configurator, *app.IBCKeeper.ClientKeeper), + upgrades.CreateV7LocalhostUpgradeHandler(app.ModuleManager, app.Configurator(), *app.IBCKeeper.ClientKeeper), ) app.UpgradeKeeper.SetUpgradeHandler( upgrades.V8, upgrades.CreateDefaultUpgradeHandler( app.ModuleManager, - app.configurator, + app.Configurator(), ), ) @@ -65,7 +65,7 @@ func (app *SimApp) registerUpgradeHandlers() { upgrades.V8_1, upgrades.CreateDefaultUpgradeHandler( app.ModuleManager, - app.configurator, + app.Configurator(), ), ) diff --git a/testing/testing_app_test.go b/testing/testing_app_test.go new file mode 100644 index 00000000000..699440dca0c --- /dev/null +++ b/testing/testing_app_test.go @@ -0,0 +1,20 @@ +package ibctesting_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + ibctesting "github.com/cosmos/ibc-go/v8/testing" +) + +// TODO: Remove this before merging. +func TestSetupTestingApp(t *testing.T) { + app, genState := ibctesting.SetupTestingApp() + + router := app.GetIBCKeeper().PortKeeper.Router + ok := router.HasRoute("mock") + require.True(t, ok) + + _, _ = app, genState +} diff --git a/testing/types/expected_keepers.go b/testing/types/expected_keepers.go index e0d3af4b878..4699f133c50 100644 --- a/testing/types/expected_keepers.go +++ b/testing/types/expected_keepers.go @@ -3,7 +3,10 @@ package types import ( "context" + sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" ) // StakingKeeper defines the expected staking keeper interface used in the @@ -11,3 +14,8 @@ import ( type StakingKeeper interface { GetHistoricalInfo(ctx context.Context, height int64) (stakingtypes.HistoricalInfo, error) } + +type ScopedKeeper interface { + ClaimCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) error + GetCapability(ctx sdk.Context, name string) (*capabilitytypes.Capability, bool) +} diff --git a/testing/values.go b/testing/values.go index 0f14f41a081..8d21715ef55 100644 --- a/testing/values.go +++ b/testing/values.go @@ -13,12 +13,12 @@ import ( "github.com/cometbft/cometbft/crypto/tmhash" + ibcfeetypes "github.com/cosmos/ibc-go/v8/modules/apps/29-fee/types" ibctransfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" connectiontypes "github.com/cosmos/ibc-go/v8/modules/core/03-connection/types" commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" ibctm "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" "github.com/cosmos/ibc-go/v8/testing/mock" - "github.com/cosmos/ibc-go/v8/testing/simapp" ) const ( @@ -39,7 +39,7 @@ const ( // Application Ports TransferPort = ibctransfertypes.ModuleName MockPort = mock.ModuleName - MockFeePort = simapp.MockFeePort + MockFeePort = mock.ModuleName + ibcfeetypes.ModuleName // used for testing proposals Title = "title"