From 9bf879f60d7b885f689cf865c45e4e73d8a07a88 Mon Sep 17 00:00:00 2001 From: Bryan White Date: Mon, 17 Feb 2025 17:23:08 +0100 Subject: [PATCH 01/18] refactor: add bank & acct mod deps to migration mod --- testutil/keeper/migration.go | 21 +++++++++++++++++++++ x/migration/keeper/keeper.go | 15 +++++++++++---- x/migration/module/module.go | 2 ++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/testutil/keeper/migration.go b/testutil/keeper/migration.go index fd85baf9f..8dcf73c38 100644 --- a/testutil/keeper/migration.go +++ b/testutil/keeper/migration.go @@ -1,6 +1,7 @@ package keeper import ( + "context" "testing" "cosmossdk.io/log" @@ -16,7 +17,9 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" + "github.com/pokt-network/poktroll/testutil/proof/mocks" "github.com/pokt-network/poktroll/x/migration/keeper" "github.com/pokt-network/poktroll/x/migration/types" ) @@ -33,11 +36,29 @@ func MigrationKeeper(t testing.TB) (keeper.Keeper, sdk.Context) { cdc := codec.NewProtoCodec(registry) authority := authtypes.NewModuleAddress(govtypes.ModuleName) + ctrl := gomock.NewController(t) + mockBankKeeper := mocks.NewMockBankKeeper(ctrl) + mockBankKeeper.EXPECT(). + SpendableCoins(gomock.Any(), gomock.Any()). + DoAndReturn( + func(ctx context.Context, addr sdk.AccAddress) sdk.Coins { + mapMu.RLock() + defer mapMu.RUnlock() + if coins, ok := mapAccAddrCoins[addr.String()]; ok { + return coins + } + return sdk.Coins{} + }, + ).AnyTimes() + mockAccountKeeper := mocks.NewMockAccountKeeper(ctrl) + k := keeper.NewKeeper( cdc, runtime.NewKVStoreService(storeKey), log.NewNopLogger(), authority.String(), + mockAccountKeeper, + mockBankKeeper, ) ctx := sdk.NewContext(stateStore, cmtproto.Header{}, false, log.NewNopLogger()) diff --git a/x/migration/keeper/keeper.go b/x/migration/keeper/keeper.go index af25b6e3d..b4019db3f 100644 --- a/x/migration/keeper/keeper.go +++ b/x/migration/keeper/keeper.go @@ -20,6 +20,9 @@ type ( // the address capable of executing a MsgUpdateParams message. Typically, this // should be the x/gov module account. authority string + + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper } ) @@ -28,6 +31,8 @@ func NewKeeper( storeService store.KVStoreService, logger log.Logger, authority string, + accountKeeper types.AccountKeeper, + bankKeeper types.BankKeeper, ) Keeper { if _, err := sdk.AccAddressFromBech32(authority); err != nil { @@ -35,10 +40,12 @@ func NewKeeper( } return Keeper{ - cdc: cdc, - storeService: storeService, - authority: authority, - logger: logger, + cdc: cdc, + storeService: storeService, + authority: authority, + logger: logger, + accountKeeper: accountKeeper, + bankKeeper: bankKeeper, } } diff --git a/x/migration/module/module.go b/x/migration/module/module.go index 9632fab53..53cb8fc7d 100644 --- a/x/migration/module/module.go +++ b/x/migration/module/module.go @@ -202,6 +202,8 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { in.StoreService, in.Logger, authority.String(), + in.AccountKeeper, + in.BankKeeper, ) m := NewAppModule( in.Cdc, From 0bcc12b3aec49085702a22b8c295f4c3b73110b0 Mon Sep 17 00:00:00 2001 From: Bryan White Date: Mon, 17 Feb 2025 17:23:18 +0100 Subject: [PATCH 02/18] chore: add mint permission to migration module --- app/app_config.go | 1 + 1 file changed, 1 insertion(+) diff --git a/app/app_config.go b/app/app_config.go index 0c91af588..64a1e8279 100644 --- a/app/app_config.go +++ b/app/app_config.go @@ -236,6 +236,7 @@ var ( {Account: sessionmoduletypes.ModuleName, Permissions: []string{authtypes.Minter, authtypes.Burner, authtypes.Staking}}, {Account: tokenomicsmoduletypes.ModuleName, Permissions: []string{authtypes.Minter, authtypes.Burner, authtypes.Staking}}, {Account: proofmoduletypes.ModuleName, Permissions: []string{authtypes.Minter, authtypes.Burner, authtypes.Staking}}, + {Account: migrationmoduletypes.ModuleName, Permissions: []string{authtypes.Minter}}, // this line is used by starport scaffolding # stargate/app/maccPerms } } From 869f596006898256f00f168fa4aecefe9aafb40c Mon Sep 17 00:00:00 2001 From: Bryan White Date: Mon, 17 Feb 2025 17:23:58 +0100 Subject: [PATCH 03/18] chore: add EventMorseAccountClaimed proto type --- api/poktroll/migration/event.pulsar.go | 754 ++++++++++++++++++++++++- proto/poktroll/migration/event.proto | 15 + x/migration/types/event.pb.go | 369 +++++++++++- 3 files changed, 1092 insertions(+), 46 deletions(-) diff --git a/api/poktroll/migration/event.pulsar.go b/api/poktroll/migration/event.pulsar.go index e6ca4fc52..603c1b800 100644 --- a/api/poktroll/migration/event.pulsar.go +++ b/api/poktroll/migration/event.pulsar.go @@ -2,7 +2,7 @@ package migration import ( - _ "cosmossdk.io/api/cosmos/base/v1beta1" + v1beta1 "cosmossdk.io/api/cosmos/base/v1beta1" fmt "fmt" _ "github.com/cosmos/cosmos-proto" runtime "github.com/cosmos/cosmos-proto/runtime" @@ -534,6 +534,617 @@ func (x *fastReflection_EventImportMorseClaimableAccounts) ProtoMethods() *proto } } +var ( + md_EventMorseAccountClaimed protoreflect.MessageDescriptor + fd_EventMorseAccountClaimed_claimed_at_height protoreflect.FieldDescriptor + fd_EventMorseAccountClaimed_claimed_balance protoreflect.FieldDescriptor + fd_EventMorseAccountClaimed_shannon_dest_address protoreflect.FieldDescriptor + fd_EventMorseAccountClaimed_morse_src_address protoreflect.FieldDescriptor +) + +func init() { + file_poktroll_migration_event_proto_init() + md_EventMorseAccountClaimed = File_poktroll_migration_event_proto.Messages().ByName("EventMorseAccountClaimed") + fd_EventMorseAccountClaimed_claimed_at_height = md_EventMorseAccountClaimed.Fields().ByName("claimed_at_height") + fd_EventMorseAccountClaimed_claimed_balance = md_EventMorseAccountClaimed.Fields().ByName("claimed_balance") + fd_EventMorseAccountClaimed_shannon_dest_address = md_EventMorseAccountClaimed.Fields().ByName("shannon_dest_address") + fd_EventMorseAccountClaimed_morse_src_address = md_EventMorseAccountClaimed.Fields().ByName("morse_src_address") +} + +var _ protoreflect.Message = (*fastReflection_EventMorseAccountClaimed)(nil) + +type fastReflection_EventMorseAccountClaimed EventMorseAccountClaimed + +func (x *EventMorseAccountClaimed) ProtoReflect() protoreflect.Message { + return (*fastReflection_EventMorseAccountClaimed)(x) +} + +func (x *EventMorseAccountClaimed) slowProtoReflect() protoreflect.Message { + mi := &file_poktroll_migration_event_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_EventMorseAccountClaimed_messageType fastReflection_EventMorseAccountClaimed_messageType +var _ protoreflect.MessageType = fastReflection_EventMorseAccountClaimed_messageType{} + +type fastReflection_EventMorseAccountClaimed_messageType struct{} + +func (x fastReflection_EventMorseAccountClaimed_messageType) Zero() protoreflect.Message { + return (*fastReflection_EventMorseAccountClaimed)(nil) +} +func (x fastReflection_EventMorseAccountClaimed_messageType) New() protoreflect.Message { + return new(fastReflection_EventMorseAccountClaimed) +} +func (x fastReflection_EventMorseAccountClaimed_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_EventMorseAccountClaimed +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_EventMorseAccountClaimed) Descriptor() protoreflect.MessageDescriptor { + return md_EventMorseAccountClaimed +} + +// 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_EventMorseAccountClaimed) Type() protoreflect.MessageType { + return _fastReflection_EventMorseAccountClaimed_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_EventMorseAccountClaimed) New() protoreflect.Message { + return new(fastReflection_EventMorseAccountClaimed) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_EventMorseAccountClaimed) Interface() protoreflect.ProtoMessage { + return (*EventMorseAccountClaimed)(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_EventMorseAccountClaimed) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.ClaimedAtHeight != int64(0) { + value := protoreflect.ValueOfInt64(x.ClaimedAtHeight) + if !f(fd_EventMorseAccountClaimed_claimed_at_height, value) { + return + } + } + if x.ClaimedBalance != nil { + value := protoreflect.ValueOfMessage(x.ClaimedBalance.ProtoReflect()) + if !f(fd_EventMorseAccountClaimed_claimed_balance, value) { + return + } + } + if x.ShannonDestAddress != "" { + value := protoreflect.ValueOfString(x.ShannonDestAddress) + if !f(fd_EventMorseAccountClaimed_shannon_dest_address, value) { + return + } + } + if x.MorseSrcAddress != "" { + value := protoreflect.ValueOfString(x.MorseSrcAddress) + if !f(fd_EventMorseAccountClaimed_morse_src_address, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_EventMorseAccountClaimed) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "poktroll.migration.EventMorseAccountClaimed.claimed_at_height": + return x.ClaimedAtHeight != int64(0) + case "poktroll.migration.EventMorseAccountClaimed.claimed_balance": + return x.ClaimedBalance != nil + case "poktroll.migration.EventMorseAccountClaimed.shannon_dest_address": + return x.ShannonDestAddress != "" + case "poktroll.migration.EventMorseAccountClaimed.morse_src_address": + return x.MorseSrcAddress != "" + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.migration.EventMorseAccountClaimed")) + } + panic(fmt.Errorf("message poktroll.migration.EventMorseAccountClaimed 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_EventMorseAccountClaimed) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "poktroll.migration.EventMorseAccountClaimed.claimed_at_height": + x.ClaimedAtHeight = int64(0) + case "poktroll.migration.EventMorseAccountClaimed.claimed_balance": + x.ClaimedBalance = nil + case "poktroll.migration.EventMorseAccountClaimed.shannon_dest_address": + x.ShannonDestAddress = "" + case "poktroll.migration.EventMorseAccountClaimed.morse_src_address": + x.MorseSrcAddress = "" + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.migration.EventMorseAccountClaimed")) + } + panic(fmt.Errorf("message poktroll.migration.EventMorseAccountClaimed 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_EventMorseAccountClaimed) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "poktroll.migration.EventMorseAccountClaimed.claimed_at_height": + value := x.ClaimedAtHeight + return protoreflect.ValueOfInt64(value) + case "poktroll.migration.EventMorseAccountClaimed.claimed_balance": + value := x.ClaimedBalance + return protoreflect.ValueOfMessage(value.ProtoReflect()) + case "poktroll.migration.EventMorseAccountClaimed.shannon_dest_address": + value := x.ShannonDestAddress + return protoreflect.ValueOfString(value) + case "poktroll.migration.EventMorseAccountClaimed.morse_src_address": + value := x.MorseSrcAddress + return protoreflect.ValueOfString(value) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.migration.EventMorseAccountClaimed")) + } + panic(fmt.Errorf("message poktroll.migration.EventMorseAccountClaimed 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_EventMorseAccountClaimed) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "poktroll.migration.EventMorseAccountClaimed.claimed_at_height": + x.ClaimedAtHeight = value.Int() + case "poktroll.migration.EventMorseAccountClaimed.claimed_balance": + x.ClaimedBalance = value.Message().Interface().(*v1beta1.Coin) + case "poktroll.migration.EventMorseAccountClaimed.shannon_dest_address": + x.ShannonDestAddress = value.Interface().(string) + case "poktroll.migration.EventMorseAccountClaimed.morse_src_address": + x.MorseSrcAddress = value.Interface().(string) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.migration.EventMorseAccountClaimed")) + } + panic(fmt.Errorf("message poktroll.migration.EventMorseAccountClaimed 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_EventMorseAccountClaimed) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "poktroll.migration.EventMorseAccountClaimed.claimed_balance": + if x.ClaimedBalance == nil { + x.ClaimedBalance = new(v1beta1.Coin) + } + return protoreflect.ValueOfMessage(x.ClaimedBalance.ProtoReflect()) + case "poktroll.migration.EventMorseAccountClaimed.claimed_at_height": + panic(fmt.Errorf("field claimed_at_height of message poktroll.migration.EventMorseAccountClaimed is not mutable")) + case "poktroll.migration.EventMorseAccountClaimed.shannon_dest_address": + panic(fmt.Errorf("field shannon_dest_address of message poktroll.migration.EventMorseAccountClaimed is not mutable")) + case "poktroll.migration.EventMorseAccountClaimed.morse_src_address": + panic(fmt.Errorf("field morse_src_address of message poktroll.migration.EventMorseAccountClaimed is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.migration.EventMorseAccountClaimed")) + } + panic(fmt.Errorf("message poktroll.migration.EventMorseAccountClaimed 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_EventMorseAccountClaimed) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "poktroll.migration.EventMorseAccountClaimed.claimed_at_height": + return protoreflect.ValueOfInt64(int64(0)) + case "poktroll.migration.EventMorseAccountClaimed.claimed_balance": + m := new(v1beta1.Coin) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + case "poktroll.migration.EventMorseAccountClaimed.shannon_dest_address": + return protoreflect.ValueOfString("") + case "poktroll.migration.EventMorseAccountClaimed.morse_src_address": + return protoreflect.ValueOfString("") + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.migration.EventMorseAccountClaimed")) + } + panic(fmt.Errorf("message poktroll.migration.EventMorseAccountClaimed 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_EventMorseAccountClaimed) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in poktroll.migration.EventMorseAccountClaimed", 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_EventMorseAccountClaimed) 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_EventMorseAccountClaimed) 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_EventMorseAccountClaimed) 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_EventMorseAccountClaimed) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*EventMorseAccountClaimed) + 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.ClaimedAtHeight != 0 { + n += 1 + runtime.Sov(uint64(x.ClaimedAtHeight)) + } + if x.ClaimedBalance != nil { + l = options.Size(x.ClaimedBalance) + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.ShannonDestAddress) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.MorseSrcAddress) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*EventMorseAccountClaimed) + 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 len(x.MorseSrcAddress) > 0 { + i -= len(x.MorseSrcAddress) + copy(dAtA[i:], x.MorseSrcAddress) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.MorseSrcAddress))) + i-- + dAtA[i] = 0x22 + } + if len(x.ShannonDestAddress) > 0 { + i -= len(x.ShannonDestAddress) + copy(dAtA[i:], x.ShannonDestAddress) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ShannonDestAddress))) + i-- + dAtA[i] = 0x1a + } + if x.ClaimedBalance != nil { + encoded, err := options.Marshal(x.ClaimedBalance) + if err != nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) + i-- + dAtA[i] = 0x12 + } + if x.ClaimedAtHeight != 0 { + i = runtime.EncodeVarint(dAtA, i, uint64(x.ClaimedAtHeight)) + i-- + dAtA[i] = 0x8 + } + 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().(*EventMorseAccountClaimed) + 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: EventMorseAccountClaimed: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: EventMorseAccountClaimed: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ClaimedAtHeight", wireType) + } + x.ClaimedAtHeight = 0 + 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++ + x.ClaimedAtHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ClaimedBalance", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if x.ClaimedBalance == nil { + x.ClaimedBalance = &v1beta1.Coin{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.ClaimedBalance); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ShannonDestAddress", wireType) + } + var stringLen 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++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.ShannonDestAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field MorseSrcAddress", wireType) + } + var stringLen 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++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.MorseSrcAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.0 @@ -603,6 +1214,70 @@ func (x *EventImportMorseClaimableAccounts) GetNumAccounts() uint64 { return 0 } +// TODO_IN_THIS_COMMIT: comments... +type EventMorseAccountClaimed struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The height (on Shannon) at which the claim was executed (i.e. claimed). + ClaimedAtHeight int64 `protobuf:"varint,1,opt,name=claimed_at_height,json=claimedAtHeight,proto3" json:"claimed_at_height,omitempty"` + // The balance which was claimed. + ClaimedBalance *v1beta1.Coin `protobuf:"bytes,2,opt,name=claimed_balance,json=claimedBalance,proto3" json:"claimed_balance,omitempty"` + // The bech32-encoded address of the Shannon account to which the claimed balance will be minted. + ShannonDestAddress string `protobuf:"bytes,3,opt,name=shannon_dest_address,json=shannonDestAddress,proto3" json:"shannon_dest_address,omitempty"` + // The hex-encoded address of the Morse account whose balance will be claimed. + MorseSrcAddress string `protobuf:"bytes,4,opt,name=morse_src_address,json=morseSrcAddress,proto3" json:"morse_src_address,omitempty"` +} + +func (x *EventMorseAccountClaimed) Reset() { + *x = EventMorseAccountClaimed{} + if protoimpl.UnsafeEnabled { + mi := &file_poktroll_migration_event_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EventMorseAccountClaimed) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EventMorseAccountClaimed) ProtoMessage() {} + +// Deprecated: Use EventMorseAccountClaimed.ProtoReflect.Descriptor instead. +func (*EventMorseAccountClaimed) Descriptor() ([]byte, []int) { + return file_poktroll_migration_event_proto_rawDescGZIP(), []int{1} +} + +func (x *EventMorseAccountClaimed) GetClaimedAtHeight() int64 { + if x != nil { + return x.ClaimedAtHeight + } + return 0 +} + +func (x *EventMorseAccountClaimed) GetClaimedBalance() *v1beta1.Coin { + if x != nil { + return x.ClaimedBalance + } + return nil +} + +func (x *EventMorseAccountClaimed) GetShannonDestAddress() string { + if x != nil { + return x.ShannonDestAddress + } + return "" +} + +func (x *EventMorseAccountClaimed) GetMorseSrcAddress() string { + if x != nil { + return x.MorseSrcAddress + } + return "" +} + var File_poktroll_migration_event_proto protoreflect.FileDescriptor var file_poktroll_migration_event_proto_rawDesc = []byte{ @@ -634,19 +1309,41 @@ var file_poktroll_migration_event_proto_rawDesc = []byte{ 0x6e, 0x75, 0x6d, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x10, 0xea, 0xde, 0x1f, 0x0c, 0x6e, 0x75, 0x6d, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x0b, 0x6e, 0x75, 0x6d, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x73, 0x42, 0xb6, 0x01, 0xd8, 0xe2, 0x1e, 0x01, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, - 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x42, 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x23, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, - 0x2f, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0xa2, 0x02, 0x03, 0x50, 0x4d, 0x58, 0xaa, 0x02, 0x12, 0x50, 0x6f, 0x6b, 0x74, - 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xca, 0x02, - 0x12, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0xe2, 0x02, 0x1e, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x4d, - 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x3a, - 0x3a, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x73, 0x22, 0xe1, 0x02, 0x0a, 0x18, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x72, 0x73, 0x65, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x12, 0x41, + 0x0a, 0x11, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x68, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x42, 0x15, 0xea, 0xde, 0x1f, 0x11, 0x63, + 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x52, 0x0f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x41, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x12, 0x5b, 0x0a, 0x0f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x5f, 0x62, 0x61, 0x6c, + 0x61, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x17, 0xc8, 0xde, 0x1f, 0x00, 0xea, 0xde, 0x1f, 0x0f, 0x63, + 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x0e, + 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x62, + 0x0a, 0x14, 0x73, 0x68, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x30, 0xea, 0xde, + 0x1f, 0x14, 0x73, 0x68, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x12, + 0x73, 0x68, 0x61, 0x6e, 0x6e, 0x6f, 0x6e, 0x44, 0x65, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x41, 0x0a, 0x11, 0x6d, 0x6f, 0x72, 0x73, 0x65, 0x5f, 0x73, 0x72, 0x63, 0x5f, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x15, 0xea, + 0xde, 0x1f, 0x11, 0x6d, 0x6f, 0x72, 0x73, 0x65, 0x5f, 0x73, 0x72, 0x63, 0x5f, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x52, 0x0f, 0x6d, 0x6f, 0x72, 0x73, 0x65, 0x53, 0x72, 0x63, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0xb6, 0x01, 0xd8, 0xe2, 0x1e, 0x01, 0x0a, 0x16, 0x63, 0x6f, + 0x6d, 0x2e, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x6d, 0x69, 0x67, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x50, 0x01, 0x5a, 0x23, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x6d, 0x69, + 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xa2, 0x02, 0x03, 0x50, 0x4d, 0x58, 0xaa, 0x02, 0x12, + 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0xca, 0x02, 0x12, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x4d, 0x69, + 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xe2, 0x02, 0x1e, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, + 0x6c, 0x6c, 0x5c, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5c, 0x47, 0x50, 0x42, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, + 0x6f, 0x6c, 0x6c, 0x3a, 0x3a, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -661,16 +1358,19 @@ func file_poktroll_migration_event_proto_rawDescGZIP() []byte { return file_poktroll_migration_event_proto_rawDescData } -var file_poktroll_migration_event_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_poktroll_migration_event_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_poktroll_migration_event_proto_goTypes = []interface{}{ (*EventImportMorseClaimableAccounts)(nil), // 0: poktroll.migration.EventImportMorseClaimableAccounts + (*EventMorseAccountClaimed)(nil), // 1: poktroll.migration.EventMorseAccountClaimed + (*v1beta1.Coin)(nil), // 2: cosmos.base.v1beta1.Coin } var file_poktroll_migration_event_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 + 2, // 0: poktroll.migration.EventMorseAccountClaimed.claimed_balance:type_name -> cosmos.base.v1beta1.Coin + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name } func init() { file_poktroll_migration_event_proto_init() } @@ -692,6 +1392,18 @@ func file_poktroll_migration_event_proto_init() { return nil } } + file_poktroll_migration_event_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EventMorseAccountClaimed); 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{ @@ -699,7 +1411,7 @@ func file_poktroll_migration_event_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_poktroll_migration_event_proto_rawDesc, NumEnums: 0, - NumMessages: 1, + NumMessages: 2, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/poktroll/migration/event.proto b/proto/poktroll/migration/event.proto index 60b013d65..3c109c4da 100644 --- a/proto/poktroll/migration/event.proto +++ b/proto/poktroll/migration/event.proto @@ -23,3 +23,18 @@ message EventImportMorseClaimableAccounts { // NOTE: Application and supplier actor stakes are consolidated into their corresponding account balances. uint64 num_accounts = 3 [(gogoproto.jsontag) = "num_accounts"]; } + +// TODO_IN_THIS_COMMIT: comments... +message EventMorseAccountClaimed { + // The height (on Shannon) at which the claim was executed (i.e. claimed). + int64 claimed_at_height = 1 [(gogoproto.jsontag) = "claimed_at_height"]; + + // The balance which was claimed. + cosmos.base.v1beta1.Coin claimed_balance = 2 [(gogoproto.jsontag) = "claimed_balance", (gogoproto.nullable) = false]; + + // The bech32-encoded address of the Shannon account to which the claimed balance will be minted. + string shannon_dest_address = 3 [(cosmos_proto.scalar) = "cosmos.AddressString", (gogoproto.jsontag) = "shannon_dest_address"]; + + // The hex-encoded address of the Morse account whose balance will be claimed. + string morse_src_address = 4 [(gogoproto.jsontag) = "morse_src_address"]; +} \ No newline at end of file diff --git a/x/migration/types/event.pb.go b/x/migration/types/event.pb.go index 9ccab2666..456a5b509 100644 --- a/x/migration/types/event.pb.go +++ b/x/migration/types/event.pb.go @@ -6,7 +6,7 @@ package types import ( fmt "fmt" _ "github.com/cosmos/cosmos-proto" - _ "github.com/cosmos/cosmos-sdk/types" + types "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" _ "github.com/pokt-network/poktroll/x/shared/types" @@ -87,37 +87,116 @@ func (m *EventImportMorseClaimableAccounts) GetNumAccounts() uint64 { return 0 } +// TODO_IN_THIS_COMMIT: comments... +type EventMorseAccountClaimed struct { + // The height (on Shannon) at which the claim was executed (i.e. claimed). + ClaimedAtHeight int64 `protobuf:"varint,1,opt,name=claimed_at_height,json=claimedAtHeight,proto3" json:"claimed_at_height"` + // The balance which was claimed. + ClaimedBalance types.Coin `protobuf:"bytes,2,opt,name=claimed_balance,json=claimedBalance,proto3" json:"claimed_balance"` + // The bech32-encoded address of the Shannon account to which the claimed balance will be minted. + ShannonDestAddress string `protobuf:"bytes,3,opt,name=shannon_dest_address,json=shannonDestAddress,proto3" json:"shannon_dest_address"` + // The hex-encoded address of the Morse account whose balance will be claimed. + MorseSrcAddress string `protobuf:"bytes,4,opt,name=morse_src_address,json=morseSrcAddress,proto3" json:"morse_src_address"` +} + +func (m *EventMorseAccountClaimed) Reset() { *m = EventMorseAccountClaimed{} } +func (m *EventMorseAccountClaimed) String() string { return proto.CompactTextString(m) } +func (*EventMorseAccountClaimed) ProtoMessage() {} +func (*EventMorseAccountClaimed) Descriptor() ([]byte, []int) { + return fileDescriptor_d5b0bc9ed37905e1, []int{1} +} +func (m *EventMorseAccountClaimed) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventMorseAccountClaimed) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *EventMorseAccountClaimed) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventMorseAccountClaimed.Merge(m, src) +} +func (m *EventMorseAccountClaimed) XXX_Size() int { + return m.Size() +} +func (m *EventMorseAccountClaimed) XXX_DiscardUnknown() { + xxx_messageInfo_EventMorseAccountClaimed.DiscardUnknown(m) +} + +var xxx_messageInfo_EventMorseAccountClaimed proto.InternalMessageInfo + +func (m *EventMorseAccountClaimed) GetClaimedAtHeight() int64 { + if m != nil { + return m.ClaimedAtHeight + } + return 0 +} + +func (m *EventMorseAccountClaimed) GetClaimedBalance() types.Coin { + if m != nil { + return m.ClaimedBalance + } + return types.Coin{} +} + +func (m *EventMorseAccountClaimed) GetShannonDestAddress() string { + if m != nil { + return m.ShannonDestAddress + } + return "" +} + +func (m *EventMorseAccountClaimed) GetMorseSrcAddress() string { + if m != nil { + return m.MorseSrcAddress + } + return "" +} + func init() { proto.RegisterType((*EventImportMorseClaimableAccounts)(nil), "poktroll.migration.EventImportMorseClaimableAccounts") + proto.RegisterType((*EventMorseAccountClaimed)(nil), "poktroll.migration.EventMorseAccountClaimed") } func init() { proto.RegisterFile("poktroll/migration/event.proto", fileDescriptor_d5b0bc9ed37905e1) } var fileDescriptor_d5b0bc9ed37905e1 = []byte{ - // 360 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x90, 0xcd, 0x8e, 0xd3, 0x30, - 0x14, 0x85, 0x6b, 0x8a, 0x58, 0x84, 0x4a, 0x40, 0x44, 0xa5, 0x50, 0x81, 0x5b, 0x58, 0xa0, 0x6e, - 0xa8, 0x55, 0xfa, 0x04, 0x0d, 0x42, 0x2a, 0x0b, 0x24, 0x54, 0xc4, 0x86, 0x4d, 0xe4, 0xb8, 0x56, - 0x1c, 0x35, 0xf6, 0x8d, 0xec, 0x9b, 0x02, 0x6f, 0xc1, 0x63, 0xb1, 0xec, 0xb2, 0xab, 0x0a, 0xa5, - 0xbb, 0x2e, 0xe7, 0x09, 0x46, 0xf9, 0xab, 0x66, 0x34, 0x33, 0x3b, 0xfb, 0x7c, 0xc7, 0xd7, 0xe7, - 0x1e, 0x8f, 0xe6, 0xb0, 0x45, 0x0b, 0x59, 0xc6, 0x74, 0x9a, 0x58, 0x8e, 0x29, 0x18, 0x26, 0x77, - 0xd2, 0xe0, 0x2c, 0xb7, 0x80, 0xe0, 0xfb, 0x1d, 0x9f, 0x5d, 0xf8, 0xe8, 0x95, 0x00, 0xa7, 0xc1, - 0x45, 0xb5, 0x83, 0x35, 0x97, 0xc6, 0x3e, 0x7a, 0x99, 0x40, 0x02, 0x8d, 0x5e, 0x9d, 0x5a, 0x95, - 0x36, 0x1e, 0x16, 0x73, 0x27, 0xd9, 0x6e, 0x1e, 0x4b, 0xe4, 0x73, 0x26, 0x20, 0x35, 0x2d, 0x7f, - 0x73, 0x09, 0xe1, 0x14, 0xb7, 0x72, 0xc3, 0x9c, 0xb4, 0xbb, 0x54, 0xc8, 0x16, 0xbf, 0xbf, 0x27, - 0xa3, 0x06, 0xeb, 0x64, 0x04, 0x46, 0x28, 0xde, 0x8d, 0x79, 0x77, 0x45, 0xbc, 0xb7, 0x9f, 0xab, - 0xec, 0x5f, 0x74, 0x0e, 0x16, 0xbf, 0x56, 0x96, 0x4f, 0x19, 0x4f, 0x35, 0x8f, 0x33, 0xb9, 0x14, - 0x02, 0x0a, 0x83, 0xce, 0x5f, 0x7a, 0x2f, 0x84, 0x95, 0x1c, 0xe5, 0x26, 0xe2, 0x18, 0x29, 0x99, - 0x26, 0x0a, 0x03, 0x32, 0x21, 0xd3, 0x7e, 0x38, 0x3c, 0x1f, 0xc7, 0x77, 0xe1, 0xfa, 0x59, 0x2b, - 0x2d, 0x71, 0x55, 0x0b, 0xfe, 0x0f, 0x2f, 0x68, 0xfe, 0xe7, 0xcd, 0xd0, 0xc8, 0x21, 0x47, 0x19, - 0x29, 0xee, 0x54, 0xf0, 0x68, 0x42, 0xa6, 0x83, 0xf0, 0xf5, 0xf9, 0x38, 0x7e, 0xd0, 0xb3, 0x1e, - 0xd6, 0xa4, 0x4d, 0xf4, 0xbd, 0xd2, 0x57, 0xdc, 0x29, 0x7f, 0xe1, 0x0d, 0x4c, 0xa1, 0xbb, 0x07, - 0x2e, 0xe8, 0x4f, 0xc8, 0xf4, 0x71, 0xf8, 0xfc, 0x7c, 0x1c, 0xdf, 0xd2, 0xd7, 0x4f, 0x4d, 0xa1, - 0xbb, 0x75, 0xc2, 0x6f, 0xff, 0x4a, 0x4a, 0xf6, 0x25, 0x25, 0x87, 0x92, 0x92, 0xff, 0x25, 0x25, - 0x7f, 0x4f, 0xb4, 0xb7, 0x3f, 0xd1, 0xde, 0xe1, 0x44, 0x7b, 0x3f, 0x3f, 0x26, 0x29, 0xaa, 0x22, - 0x9e, 0x09, 0xd0, 0xac, 0x6a, 0xf1, 0x83, 0x91, 0xf8, 0x0b, 0xec, 0x96, 0x5d, 0x2a, 0xfd, 0x7d, - 0xa3, 0x54, 0xfc, 0x93, 0x4b, 0x17, 0x3f, 0xa9, 0xdb, 0x5c, 0x5c, 0x07, 0x00, 0x00, 0xff, 0xff, - 0xe7, 0xcb, 0xa5, 0x40, 0x1b, 0x02, 0x00, 0x00, + // 501 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xcf, 0x6e, 0xd3, 0x40, + 0x10, 0xc6, 0xe3, 0xb6, 0x42, 0xc2, 0xad, 0x08, 0x58, 0xa9, 0x48, 0x2b, 0xb0, 0x43, 0x0f, 0x28, + 0x97, 0xda, 0xb4, 0x7d, 0x82, 0xb8, 0x20, 0x95, 0x43, 0x25, 0xe4, 0x88, 0x0b, 0x1c, 0xac, 0xf5, + 0x7a, 0x64, 0x5b, 0x8d, 0x77, 0xa3, 0xdd, 0x49, 0x80, 0xb7, 0xe0, 0x61, 0x78, 0x88, 0x1e, 0x2b, + 0x4e, 0x3d, 0x59, 0x90, 0xdc, 0x7c, 0xe4, 0x09, 0x90, 0x77, 0xd7, 0x56, 0xff, 0xde, 0x76, 0x7f, + 0xdf, 0xec, 0xcc, 0x7c, 0x3b, 0x63, 0xbb, 0x73, 0x7e, 0x81, 0x82, 0xcf, 0x66, 0x41, 0x59, 0x64, + 0x82, 0x60, 0xc1, 0x59, 0x00, 0x4b, 0x60, 0xe8, 0xcf, 0x05, 0x47, 0xee, 0x38, 0xad, 0xee, 0x77, + 0xfa, 0xfe, 0x1e, 0xe5, 0xb2, 0xe4, 0x32, 0x56, 0x11, 0x81, 0xbe, 0xe8, 0xf0, 0xfd, 0x41, 0xc6, + 0x33, 0xae, 0x79, 0x73, 0x32, 0xd4, 0xd5, 0x31, 0x41, 0x42, 0x24, 0x04, 0xcb, 0xa3, 0x04, 0x90, + 0x1c, 0x05, 0x94, 0x17, 0xcc, 0xe8, 0xaf, 0xbb, 0x26, 0x64, 0x4e, 0x04, 0xa4, 0x81, 0x04, 0xb1, + 0x2c, 0x28, 0x18, 0xf9, 0xed, 0x03, 0x3d, 0x96, 0x5c, 0x48, 0x88, 0x39, 0xa3, 0x39, 0x69, 0xd3, + 0x1c, 0xfc, 0xb3, 0xec, 0x37, 0x1f, 0x9a, 0xde, 0x3f, 0x96, 0x73, 0x2e, 0xf0, 0xbc, 0x09, 0x39, + 0x9d, 0x91, 0xa2, 0x24, 0xc9, 0x0c, 0x26, 0x94, 0xf2, 0x05, 0x43, 0xe9, 0x4c, 0xec, 0x17, 0x54, + 0x00, 0x41, 0x48, 0x63, 0x82, 0x71, 0x0e, 0x45, 0x96, 0xe3, 0xd0, 0x1a, 0x59, 0xe3, 0xcd, 0x70, + 0xb7, 0xae, 0xbc, 0xfb, 0x62, 0xd4, 0x37, 0x68, 0x82, 0x67, 0x0a, 0x38, 0x9f, 0xed, 0xa1, 0xae, + 0x4f, 0x74, 0xd2, 0x58, 0x22, 0x41, 0x88, 0x73, 0x22, 0xf3, 0xe1, 0xc6, 0xc8, 0x1a, 0xef, 0x84, + 0xaf, 0xea, 0xca, 0x7b, 0x34, 0x26, 0xda, 0x55, 0x8a, 0xe9, 0x68, 0xda, 0xf0, 0x33, 0x22, 0x73, + 0xe7, 0xc4, 0xde, 0x61, 0x8b, 0xb2, 0x7d, 0x20, 0x87, 0x9b, 0x23, 0x6b, 0xbc, 0x15, 0x3e, 0xaf, + 0x2b, 0xef, 0x16, 0x8f, 0xb6, 0xd9, 0xa2, 0x6c, 0xed, 0x1c, 0xfc, 0xdd, 0xb0, 0x87, 0xca, 0xf4, + 0xf9, 0x8d, 0x9c, 0xca, 0x35, 0xa4, 0xca, 0xab, 0x3e, 0x3e, 0xe2, 0xf5, 0xae, 0x18, 0xf5, 0x0d, + 0xea, 0xbc, 0x7e, 0xb5, 0x5b, 0x14, 0x27, 0x64, 0x46, 0x18, 0x05, 0x65, 0x71, 0xfb, 0x78, 0xcf, + 0x37, 0x93, 0x6f, 0xa6, 0xea, 0x9b, 0xa9, 0xfa, 0xa7, 0xbc, 0x60, 0xe1, 0xcb, 0xcb, 0xca, 0xeb, + 0xd5, 0x95, 0x77, 0xf7, 0x65, 0xf4, 0xcc, 0x80, 0x50, 0xdf, 0x9d, 0xc4, 0x1e, 0xc8, 0x9c, 0x30, + 0xc6, 0x59, 0x9c, 0x82, 0xc4, 0x98, 0xa4, 0xa9, 0x00, 0xa9, 0x9d, 0x3f, 0x0d, 0xdf, 0xd5, 0x95, + 0xf7, 0xa0, 0xfe, 0xfb, 0xd7, 0xe1, 0xc0, 0x14, 0x9f, 0x68, 0x32, 0x45, 0x51, 0xb0, 0x2c, 0x72, + 0x4c, 0xf4, 0x7b, 0x90, 0x68, 0x94, 0xe6, 0x0f, 0xf4, 0x20, 0xa4, 0xa0, 0x5d, 0x81, 0x2d, 0x55, + 0x40, 0xfd, 0xc1, 0x3d, 0x31, 0xea, 0x2b, 0x34, 0x15, 0xd4, 0xa4, 0x08, 0x3f, 0x5d, 0xae, 0x5c, + 0xeb, 0x6a, 0xe5, 0x5a, 0xd7, 0x2b, 0xd7, 0xfa, 0xb3, 0x72, 0xad, 0x9f, 0x6b, 0xb7, 0x77, 0xb5, + 0x76, 0x7b, 0xd7, 0x6b, 0xb7, 0xf7, 0xe5, 0x38, 0x2b, 0x30, 0x5f, 0x24, 0x3e, 0xe5, 0x65, 0xd0, + 0x6c, 0xea, 0x21, 0x03, 0xfc, 0xc6, 0xc5, 0x45, 0xd0, 0xad, 0xed, 0xf7, 0x1b, 0x8b, 0x8b, 0x3f, + 0xe6, 0x20, 0x93, 0x27, 0x6a, 0x63, 0x4f, 0xfe, 0x07, 0x00, 0x00, 0xff, 0xff, 0x5a, 0x11, 0x5d, + 0x08, 0x7f, 0x03, 0x00, 0x00, } func (m *EventImportMorseClaimableAccounts) Marshal() (dAtA []byte, err error) { @@ -160,6 +239,58 @@ func (m *EventImportMorseClaimableAccounts) MarshalToSizedBuffer(dAtA []byte) (i return len(dAtA) - i, nil } +func (m *EventMorseAccountClaimed) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *EventMorseAccountClaimed) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventMorseAccountClaimed) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.MorseSrcAddress) > 0 { + i -= len(m.MorseSrcAddress) + copy(dAtA[i:], m.MorseSrcAddress) + i = encodeVarintEvent(dAtA, i, uint64(len(m.MorseSrcAddress))) + i-- + dAtA[i] = 0x22 + } + if len(m.ShannonDestAddress) > 0 { + i -= len(m.ShannonDestAddress) + copy(dAtA[i:], m.ShannonDestAddress) + i = encodeVarintEvent(dAtA, i, uint64(len(m.ShannonDestAddress))) + i-- + dAtA[i] = 0x1a + } + { + size, err := m.ClaimedBalance.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvent(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if m.ClaimedAtHeight != 0 { + i = encodeVarintEvent(dAtA, i, uint64(m.ClaimedAtHeight)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarintEvent(dAtA []byte, offset int, v uint64) int { offset -= sovEvent(v) base := offset @@ -190,6 +321,28 @@ func (m *EventImportMorseClaimableAccounts) Size() (n int) { return n } +func (m *EventMorseAccountClaimed) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ClaimedAtHeight != 0 { + n += 1 + sovEvent(uint64(m.ClaimedAtHeight)) + } + l = m.ClaimedBalance.Size() + n += 1 + l + sovEvent(uint64(l)) + l = len(m.ShannonDestAddress) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + l = len(m.MorseSrcAddress) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + return n +} + func sovEvent(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -318,6 +471,172 @@ func (m *EventImportMorseClaimableAccounts) Unmarshal(dAtA []byte) error { } return nil } +func (m *EventMorseAccountClaimed) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: EventMorseAccountClaimed: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventMorseAccountClaimed: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ClaimedAtHeight", wireType) + } + m.ClaimedAtHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ClaimedAtHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClaimedBalance", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ClaimedBalance.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ShannonDestAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ShannonDestAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MorseSrcAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MorseSrcAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvent(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvent + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipEvent(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 From 774713d0db8d55216cc7babbc919cd2e1654b8b9 Mon Sep 17 00:00:00 2001 From: Bryan White Date: Mon, 17 Feb 2025 17:24:14 +0100 Subject: [PATCH 04/18] feat: implement morse account claiming --- .../keeper/msg_server_claim_morse_account.go | 106 +++++++++++++++++- x/migration/types/errors.go | 7 +- x/migration/types/expected_keepers.go | 2 + .../types/message_claim_morse_account.go | 22 +++- 4 files changed, 125 insertions(+), 12 deletions(-) diff --git a/x/migration/keeper/msg_server_claim_morse_account.go b/x/migration/keeper/msg_server_claim_morse_account.go index afb6ec19e..7aca9d728 100644 --- a/x/migration/keeper/msg_server_claim_morse_account.go +++ b/x/migration/keeper/msg_server_claim_morse_account.go @@ -3,16 +3,110 @@ package keeper import ( "context" - sdk "github.com/cosmos/cosmos-sdk/types" + cosmostypes "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/errors" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" migrationtypes "github.com/pokt-network/poktroll/x/migration/types" ) -func (k msgServer) ClaimMorseAccount(goCtx context.Context, msg *migrationtypes.MsgClaimMorseAccount) (*migrationtypes.MsgClaimMorseAccountResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) +func (k msgServer) ClaimMorseAccount(ctx context.Context, msg *migrationtypes.MsgClaimMorseAccount) (*migrationtypes.MsgClaimMorseAccountResponse, error) { + sdkCtx := cosmostypes.UnwrapSDKContext(ctx) - // TODO_UPNEXT(@bryanchriswhite#1034): Handling the message - _ = ctx + if err := msg.ValidateBasic(); err != nil { + return nil, status.Error( + codes.InvalidArgument, + migrationtypes.ErrMorseClaimableAccount.Wrap(err.Error()).Error(), + ) + } - return &migrationtypes.MsgClaimMorseAccountResponse{}, nil + shannonAccAddr, err := cosmostypes.AccAddressFromBech32(msg.ShannonDestAddress) + // DEV_NOTE: This SHOULD NEVER happen as the shannonDestAddress is validated + // in MsgClaimMorseAccount#ValidateBasic(). + if err != nil { + return nil, status.Error( + codes.InvalidArgument, + errors.ErrInvalidAddress.Wrapf( + "failed to parse shannon destination address (%s): %s", + msg.ShannonDestAddress, err, + ).Error(), + ) + } + + // Ensure that a claim for the given morseSrcAddress does not already exist. + morseAccountClaim, isFound := k.GetMorseClaimableAccount( + sdkCtx, + msg.MorseSrcAddress, + ) + if !isFound { + return nil, status.Error( + codes.NotFound, + migrationtypes.ErrMorseClaimableAccount.Wrapf( + "no morse claimable account exists with address %q", + msg.MorseSrcAddress, + ).Error(), + ) + } + + k.SetMorseClaimableAccount( + sdkCtx, + morseAccountClaim, + ) + + // Add any actor stakes to the account balance because we're not creating + // a shannon actor (i.e. not a re-stake claim). + totalTokens := morseAccountClaim.UnstakedBalance. + Add(morseAccountClaim.ApplicationStake). + Add(morseAccountClaim.SupplierStake) + + // Mint the sum of the account balance (totalTokens) and any actor stakes to the migration module account. + if err = k.bankKeeper.MintCoins(ctx, migrationtypes.ModuleName, cosmostypes.NewCoins(totalTokens)); err != nil { + return nil, status.Error( + codes.Internal, + migrationtypes.ErrMorseClaimableAccount.Wrapf( + "failed to mint coins: %v", + err, + ).Error(), + ) + } + + // Transfer the totalTokens to the shannonDestAddress account. + if err = k.bankKeeper.SendCoinsFromModuleToAccount(ctx, + migrationtypes.ModuleName, + shannonAccAddr, + cosmostypes.NewCoins(totalTokens), + ); err != nil { + return nil, status.Error( + codes.Internal, + migrationtypes.ErrMorseClaimableAccount.Wrapf( + "failed to send coins: %v", + err, + ).Error(), + ) + } + + // Emit an event which signals that the morse account has been claimed. + event := migrationtypes.EventMorseAccountClaimed{ + ClaimedAtHeight: sdkCtx.BlockHeight(), + ShannonDestAddress: msg.ShannonDestAddress, + MorseSrcAddress: msg.MorseSrcAddress, + ClaimedBalance: totalTokens, + } + if err = sdkCtx.EventManager().EmitTypedEvent(&event); err != nil { + return nil, status.Error( + codes.Internal, + migrationtypes.ErrMorseClaimableAccount.Wrapf( + "failed to emit event type %T: %v", + &event, + err, + ).Error(), + ) + } + + return &migrationtypes.MsgClaimMorseAccountResponse{ + MorseSrcAddress: msg.MorseSrcAddress, + ClaimedBalance: totalTokens, + ClaimedAtHeight: sdkCtx.BlockHeight(), + }, nil } diff --git a/x/migration/types/errors.go b/x/migration/types/errors.go index d49cef446..c5f3f5bd8 100644 --- a/x/migration/types/errors.go +++ b/x/migration/types/errors.go @@ -8,7 +8,8 @@ import ( // x/migration module sentinel errors var ( - ErrInvalidSigner = sdkerrors.Register(ModuleName, 1100, "expected gov account as only signer for proposal message") - ErrMorseAccountState = sdkerrors.Register(ModuleName, 1101, "morse account state is invalid") - ErrUnauthorized = sdkerrors.Register(ModuleName, 1102, "unauthorized") + ErrInvalidSigner = sdkerrors.Register(ModuleName, 1100, "expected gov account as only signer for proposal message") + ErrMorseAccountState = sdkerrors.Register(ModuleName, 1101, "morse account state is invalid") + ErrUnauthorized = sdkerrors.Register(ModuleName, 1102, "unauthorized") + ErrMorseClaimableAccount = sdkerrors.Register(ModuleName, 1103, "morse claimable account is invalid") ) diff --git a/x/migration/types/expected_keepers.go b/x/migration/types/expected_keepers.go index 4a50d01a9..3902ed53a 100644 --- a/x/migration/types/expected_keepers.go +++ b/x/migration/types/expected_keepers.go @@ -15,6 +15,8 @@ type AccountKeeper interface { // BankKeeper defines the expected interface for the Bank module. type BankKeeper interface { SpendableCoins(context.Context, sdk.AccAddress) sdk.Coins + MintCoins(ctx context.Context, moduleName string, amt sdk.Coins) error + SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error // Methods imported from bank should be defined here } diff --git a/x/migration/types/message_claim_morse_account.go b/x/migration/types/message_claim_morse_account.go index 585857d19..261a3b0ae 100644 --- a/x/migration/types/message_claim_morse_account.go +++ b/x/migration/types/message_claim_morse_account.go @@ -1,19 +1,35 @@ package types import ( + "encoding/hex" + errorsmod "cosmossdk.io/errors" + cometcrypto "github.com/cometbft/cometbft/crypto/ed25519" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/gogoproto/proto" ) var _ sdk.Msg = &MsgClaimMorseAccount{} -func NewMsgClaimMorseAccount(shannonDestAddress string, morseSrcAddress string, morseSignature string) *MsgClaimMorseAccount { - return &MsgClaimMorseAccount{ +func NewMsgClaimMorseAccount( + shannonDestAddress string, + morseSrcAddress string, + morsePrivateKey cometcrypto.PrivKey, +) (*MsgClaimMorseAccount, error) { + msg := &MsgClaimMorseAccount{ ShannonDestAddress: shannonDestAddress, MorseSrcAddress: morseSrcAddress, - MorseSignature: morseSignature, } + msgBz, err := proto.Marshal(msg) + if err != nil { + return nil, err + } + + morseSignature, err := morsePrivateKey.Sign(msgBz) + msg.MorseSignature = hex.EncodeToString(morseSignature) + + return msg, nil } func (msg *MsgClaimMorseAccount) ValidateBasic() error { From 44165d4a3162dc36f63cbdb2bf1f2510ffd4134e Mon Sep 17 00:00:00 2001 From: Bryan White Date: Mon, 17 Feb 2025 17:24:19 +0100 Subject: [PATCH 05/18] test: unit Morse account claiming --- .../msg_server_claim_morse_acount_test.go | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 x/migration/keeper/msg_server_claim_morse_acount_test.go diff --git a/x/migration/keeper/msg_server_claim_morse_acount_test.go b/x/migration/keeper/msg_server_claim_morse_acount_test.go new file mode 100644 index 000000000..6b38a1e41 --- /dev/null +++ b/x/migration/keeper/msg_server_claim_morse_acount_test.go @@ -0,0 +1,49 @@ +package keeper_test + +import ( + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + "github.com/pokt-network/poktroll/app/volatile" + keepertest "github.com/pokt-network/poktroll/testutil/keeper" + "github.com/pokt-network/poktroll/testutil/sample" + "github.com/pokt-network/poktroll/x/migration/keeper" + "github.com/pokt-network/poktroll/x/migration/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestMorseAccountClaimMsgServerCreate(t *testing.T) { + k, ctx := keepertest.MigrationKeeper(t) + srv := keeper.NewMsgServerImpl(k) + for i := 0; i < 5; i++ { + msgClaim := &types.MsgClaimMorseAccount{ + ShannonDestAddress: sample.AccAddress(), + MorseSrcAddress: sample.MorseAddressHex(), + } + _, err := srv.ClaimMorseAccount(ctx, msgClaim) + require.NoError(t, err) + rst, found := k.GetMorseClaimableAccount(ctx, + msgClaim.MorseSrcAddress, + ) + require.True(t, found) + + expectedRes := &types.MsgClaimMorseAccountResponse{ + MorseSrcAddress: msgClaim.MorseSrcAddress, + ClaimedBalance: sdk.NewInt64Coin(volatile.DenomuPOKT, 0), + ClaimedAtHeight: 0, + } + require.Equal(t, expectedRes, rst) + + // assert each event was emitted... + // assert that the morse account was clamed... + } +} + +// TODO_IN_THIS_COMMIT: error cases... +// - invalid ValidateBasic() +// - MorseClaimableAccount not found From 9280288b275865d4eafb77891adb3b1265ae64e7 Mon Sep 17 00:00:00 2001 From: Bryan White Date: Mon, 17 Feb 2025 17:24:26 +0100 Subject: [PATCH 06/18] test: integration morse account claim --- .../morse_account_import_and_claim_test.go | 111 ++++++++++++++++++ testutil/integration/app.go | 58 +++++---- testutil/integration/suites/param_configs.go | 13 ++ testutil/integration/suites/update_params.go | 2 + testutil/keeper/migration.go | 11 +- testutil/keeper/tokenomics.go | 21 ++++ testutil/testmigration/fixtures.go | 20 +++- x/tokenomics/types/expected_keepers.go | 7 ++ 8 files changed, 210 insertions(+), 33 deletions(-) create mode 100644 tests/integration/migration/morse_account_import_and_claim_test.go diff --git a/tests/integration/migration/morse_account_import_and_claim_test.go b/tests/integration/migration/morse_account_import_and_claim_test.go new file mode 100644 index 000000000..6d7715f50 --- /dev/null +++ b/tests/integration/migration/morse_account_import_and_claim_test.go @@ -0,0 +1,111 @@ +package migration + +import ( + "testing" + + "cosmossdk.io/depinject" + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/stretchr/testify/require" + + "github.com/pokt-network/poktroll/app/volatile" + "github.com/pokt-network/poktroll/cmd/poktrolld/cmd" + "github.com/pokt-network/poktroll/pkg/client/query" + "github.com/pokt-network/poktroll/testutil/integration" + "github.com/pokt-network/poktroll/testutil/sample" + "github.com/pokt-network/poktroll/testutil/testmigration" + migrationtypes "github.com/pokt-network/poktroll/x/migration/types" +) + +// TODO_IN_THIS_COMMIT: confirm whether this is necessary... +func init() { + cmd.InitSDKConfig() +} + +func TestMsgServer_CreateMorseAccountClaim(t *testing.T) { + app := integration.NewCompleteIntegrationApp(t) + + // Generate Morse claimable accounts. + numAccounts := 10 + _, accountState := testmigration.NewMorseStateExportAndAccountState(t, numAccounts) + + msgImport, err := migrationtypes.NewMsgImportMorseClaimableAccounts( + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + *accountState, + ) + require.NoError(t, err) + + // Import Morse claimable accounts. + resAny, err := app.RunMsg(t, msgImport) + require.NoError(t, err) + + msgImportRes, ok := resAny.(*migrationtypes.MsgImportMorseClaimableAccountsResponse) + require.True(t, ok) + + morseAccountStateHash, err := accountState.GetHash() + require.NoError(t, err) + + expectedMsgImportRes := &migrationtypes.MsgImportMorseClaimableAccountsResponse{ + StateHash: morseAccountStateHash, + NumAccounts: uint64(numAccounts), + } + require.Equal(t, expectedMsgImportRes, msgImportRes) + + deps := depinject.Supply(app.QueryHelper()) + bankClient, err := query.NewBankQuerier(deps) + require.NoError(t, err) + + // Assert that the shannonDestAddr account initially has a zero balance. + shannonDestAddr := sample.AccAddress() + shannonDestBalance, err := bankClient.GetBalance(app.GetSdkCtx(), shannonDestAddr) + require.NoError(t, err) + require.Equal(t, int64(0), shannonDestBalance.Amount.Int64()) + + morsePrivateKey := testmigration.NewMorsePrivateKey(t, 1) + morseDestAddr := morsePrivateKey.PubKey().Address().String() + require.Equal(t, morseDestAddr, accountState.Accounts[0].MorseSrcAddress) + + morseClaimMsg, err := migrationtypes.NewMsgClaimMorseAccount( + shannonDestAddr, + morseDestAddr, + morsePrivateKey, + ) + require.NoError(t, err) + + // Claim a Morse claimable account. + resAny, err = app.RunMsg(t, morseClaimMsg) + require.NoError(t, err) + + expectedBalance := sdk.NewInt64Coin(volatile.DenomuPOKT, 1110111) + expectedClaimAccountRes := &migrationtypes.MsgClaimMorseAccountResponse{ + MorseSrcAddress: morseDestAddr, + ClaimedBalance: expectedBalance, + ClaimedAtHeight: app.GetSdkCtx().BlockHeight() - 1, + } + + claimAccountRes, ok := resAny.(*migrationtypes.MsgClaimMorseAccountResponse) + require.True(t, ok) + require.Equal(t, expectedClaimAccountRes, claimAccountRes) + + // Assert that the MorseClaimableAccount was updated on-chain. + expectedMorseClaimableAccount := accountState.Accounts[0] + morseAccountQuerier := migrationtypes.NewQueryClient(app.QueryHelper()) + morseClaimableAcctRes, err := morseAccountQuerier.MorseClaimableAccount(app.GetSdkCtx(), &migrationtypes.QueryGetMorseClaimableAccountRequest{ + Address: morseDestAddr, + }) + require.NoError(t, err) + require.Equal(t, *expectedMorseClaimableAccount, morseClaimableAcctRes.MorseClaimableAccount) + + // Assert that the shannonDestAddr account balance has been updated. + shannonDestBalance, err = bankClient.GetBalance(app.GetSdkCtx(), shannonDestAddr) + require.NoError(t, err) + require.Equal(t, expectedBalance, *shannonDestBalance) + + // Assert that the migration module account balance returns to zero. + migrationModuleAddress := authtypes.NewModuleAddress(migrationtypes.ModuleName).String() + migrationModuleBalance, err := bankClient.GetBalance(app.GetSdkCtx(), migrationModuleAddress) + require.NoError(t, err) + require.Equal(t, sdk.NewCoin(volatile.DenomuPOKT, math.ZeroInt()), *migrationModuleBalance) +} diff --git a/testutil/integration/app.go b/testutil/integration/app.go index 04305089a..c2ce36e89 100644 --- a/testutil/integration/app.go +++ b/testutil/integration/app.go @@ -61,6 +61,9 @@ import ( gatewaykeeper "github.com/pokt-network/poktroll/x/gateway/keeper" gateway "github.com/pokt-network/poktroll/x/gateway/module" gatewaytypes "github.com/pokt-network/poktroll/x/gateway/types" + migrationkeeper "github.com/pokt-network/poktroll/x/migration/keeper" + migration "github.com/pokt-network/poktroll/x/migration/module" + migrationtypes "github.com/pokt-network/poktroll/x/migration/types" proofkeeper "github.com/pokt-network/poktroll/x/proof/keeper" proof "github.com/pokt-network/poktroll/x/proof/module" prooftypes "github.com/pokt-network/poktroll/x/proof/types" @@ -273,6 +276,7 @@ func NewCompleteIntegrationApp(t *testing.T, opts ...IntegrationAppOptionFn) *Ap cosmostypes.RegisterInterfaces(registry) cryptocodec.RegisterInterfaces(registry) banktypes.RegisterInterfaces(registry) + migrationtypes.RegisterInterfaces(registry) // Prepare all the store keys storeKeys := storetypes.NewKVStoreKeys( @@ -287,6 +291,7 @@ func NewCompleteIntegrationApp(t *testing.T, opts ...IntegrationAppOptionFn) *Ap prooftypes.StoreKey, servicetypes.StoreKey, authtypes.StoreKey, + migrationtypes.StoreKey, ) // Prepare the codec @@ -322,6 +327,7 @@ func NewCompleteIntegrationApp(t *testing.T, opts ...IntegrationAppOptionFn) *Ap apptypes.ModuleName: {authtypes.Minter, authtypes.Burner, authtypes.Staking}, suppliertypes.ModuleName: {authtypes.Minter, authtypes.Burner, authtypes.Staking}, prooftypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + migrationtypes.ModuleName: {authtypes.Minter}, } // Prepare the account keeper and module @@ -512,6 +518,22 @@ func NewCompleteIntegrationApp(t *testing.T, opts ...IntegrationAppOptionFn) *Ap supplierKeeper, ) + // Prepare the migration keeper and module + migrationKeeper := migrationkeeper.NewKeeper( + cdc, + runtime.NewKVStoreService(storeKeys[migrationtypes.StoreKey]), + logger, + authority.String(), + accountKeeper, + bankKeeper, + ) + migrationModule := migration.NewAppModule( + cdc, + migrationKeeper, + accountKeeper, + bankKeeper, + ) + // Prepare the message & query routers msgRouter := baseapp.NewMsgServiceRouter() queryHelper := baseapp.NewQueryServerTestHelper(sdkCtx, registry) @@ -544,6 +566,7 @@ func NewCompleteIntegrationApp(t *testing.T, opts ...IntegrationAppOptionFn) *Ap prooftypes.ModuleName: proofModule, authtypes.ModuleName: authModule, sessiontypes.ModuleName: sessionModule, + migrationtypes.ModuleName: migrationModule, } // Initialize the integration integrationApp @@ -563,32 +586,11 @@ func NewCompleteIntegrationApp(t *testing.T, opts ...IntegrationAppOptionFn) *Ap opts..., ) - // Register the message servers - banktypes.RegisterMsgServer(msgRouter, bankkeeper.NewMsgServerImpl(bankKeeper)) - tokenomicstypes.RegisterMsgServer(msgRouter, tokenomicskeeper.NewMsgServerImpl(tokenomicsKeeper)) - servicetypes.RegisterMsgServer(msgRouter, servicekeeper.NewMsgServerImpl(serviceKeeper)) - sharedtypes.RegisterMsgServer(msgRouter, sharedkeeper.NewMsgServerImpl(sharedKeeper)) - gatewaytypes.RegisterMsgServer(msgRouter, gatewaykeeper.NewMsgServerImpl(gatewayKeeper)) - apptypes.RegisterMsgServer(msgRouter, appkeeper.NewMsgServerImpl(applicationKeeper)) - suppliertypes.RegisterMsgServer(msgRouter, supplierkeeper.NewMsgServerImpl(supplierKeeper)) - prooftypes.RegisterMsgServer(msgRouter, proofkeeper.NewMsgServerImpl(proofKeeper)) - authtypes.RegisterMsgServer(msgRouter, authkeeper.NewMsgServerImpl(accountKeeper)) - sessiontypes.RegisterMsgServer(msgRouter, sessionkeeper.NewMsgServerImpl(sessionKeeper)) - authz.RegisterMsgServer(msgRouter, authzKeeper) - - // Register query servers - banktypes.RegisterQueryServer(queryHelper, bankKeeper) - authz.RegisterQueryServer(queryHelper, authzKeeper) - tokenomicstypes.RegisterQueryServer(queryHelper, tokenomicsKeeper) - servicetypes.RegisterQueryServer(queryHelper, serviceKeeper) - sharedtypes.RegisterQueryServer(queryHelper, sharedKeeper) - gatewaytypes.RegisterQueryServer(queryHelper, gatewayKeeper) - apptypes.RegisterQueryServer(queryHelper, applicationKeeper) - suppliertypes.RegisterQueryServer(queryHelper, supplierKeeper) - prooftypes.RegisterQueryServer(queryHelper, proofKeeper) - // TODO_TECHDEBT: What is the query server for authtypes? - // authtypes.RegisterQueryServer(queryHelper, accountKeeper) - sessiontypes.RegisterQueryServer(queryHelper, sessionKeeper) + // Register the message & query servers. + configurator := module.NewConfigurator(cdc, msgRouter, queryHelper) + for _, mod := range integrationApp.GetModuleManager().Modules { + mod.(module.HasServices).RegisterServices(configurator) + } // Need to go to the next block to finalize the genesis and setup. // This has to be after the params are set, as the params are stored in the @@ -963,6 +965,10 @@ func (app *App) setupDefaultActorsState( app.NextBlock(t) } +func (app *App) GetModuleManager() module.Manager { + return app.moduleManager +} + // fundAccount mints and sends amountUpokt tokens to the given recipientAddr. // // TODO_IMPROVE: Eliminate usage of and remove this function in favor of diff --git a/testutil/integration/suites/param_configs.go b/testutil/integration/suites/param_configs.go index 5d0d09838..4acf0d132 100644 --- a/testutil/integration/suites/param_configs.go +++ b/testutil/integration/suites/param_configs.go @@ -7,6 +7,7 @@ import ( "github.com/pokt-network/poktroll/testutil/sample" apptypes "github.com/pokt-network/poktroll/x/application/types" gatewaytypes "github.com/pokt-network/poktroll/x/gateway/types" + migrationtypes "github.com/pokt-network/poktroll/x/migration/types" prooftypes "github.com/pokt-network/poktroll/x/proof/types" servicetypes "github.com/pokt-network/poktroll/x/service/types" sessiontypes "github.com/pokt-network/poktroll/x/session/types" @@ -246,4 +247,16 @@ var ( DefaultParams: tokenomicstypes.DefaultParams(), NewParamClientFn: tokenomicstypes.NewQueryClient, } + + MigrationModuleParamConfig = ModuleParamConfig{ + ParamsMsgs: ModuleParamsMessages{ + MsgUpdateParams: migrationtypes.MsgUpdateParams{}, + MsgUpdateParamsResponse: migrationtypes.MsgUpdateParamsResponse{}, + QueryParamsRequest: migrationtypes.QueryParamsRequest{}, + QueryParamsResponse: migrationtypes.QueryParamsResponse{}, + }, + ValidParams: migrationtypes.DefaultParams(), + DefaultParams: migrationtypes.DefaultParams(), + NewParamClientFn: migrationtypes.NewQueryClient, + } ) diff --git a/testutil/integration/suites/update_params.go b/testutil/integration/suites/update_params.go index edc5ccabb..35ff026ee 100644 --- a/testutil/integration/suites/update_params.go +++ b/testutil/integration/suites/update_params.go @@ -14,6 +14,7 @@ import ( "github.com/pokt-network/poktroll/testutil/cases" apptypes "github.com/pokt-network/poktroll/x/application/types" gatewaytypes "github.com/pokt-network/poktroll/x/gateway/types" + migrationtypes "github.com/pokt-network/poktroll/x/migration/types" prooftypes "github.com/pokt-network/poktroll/x/proof/types" servicetypes "github.com/pokt-network/poktroll/x/service/types" sessiontypes "github.com/pokt-network/poktroll/x/session/types" @@ -45,6 +46,7 @@ var ( suppliertypes.ModuleName: SupplierModuleParamConfig, prooftypes.ModuleName: ProofModuleParamConfig, tokenomicstypes.ModuleName: TokenomicsModuleParamConfig, + migrationtypes.ModuleName: MigrationModuleParamConfig, } // paramConfigsPath is the path, relative to the project root, to the go file diff --git a/testutil/keeper/migration.go b/testutil/keeper/migration.go index 8dcf73c38..363ac76e1 100644 --- a/testutil/keeper/migration.go +++ b/testutil/keeper/migration.go @@ -19,7 +19,7 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" - "github.com/pokt-network/poktroll/testutil/proof/mocks" + "github.com/pokt-network/poktroll/testutil/migration/mocks" "github.com/pokt-network/poktroll/x/migration/keeper" "github.com/pokt-network/poktroll/x/migration/types" ) @@ -50,6 +50,15 @@ func MigrationKeeper(t testing.TB) (keeper.Keeper, sdk.Context) { return sdk.Coins{} }, ).AnyTimes() + + mockBankKeeper.EXPECT(). + MintCoins(gomock.Any(), gomock.Any(), gomock.Any()). + AnyTimes() + + mockBankKeeper.EXPECT(). + SendCoinsFromModuleToAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + AnyTimes() + mockAccountKeeper := mocks.NewMockAccountKeeper(ctrl) k := keeper.NewKeeper( diff --git a/testutil/keeper/tokenomics.go b/testutil/keeper/tokenomics.go index 1be0f350f..f3c70cc99 100644 --- a/testutil/keeper/tokenomics.go +++ b/testutil/keeper/tokenomics.go @@ -36,6 +36,8 @@ import ( apptypes "github.com/pokt-network/poktroll/x/application/types" gatewaykeeper "github.com/pokt-network/poktroll/x/gateway/keeper" gatewaytypes "github.com/pokt-network/poktroll/x/gateway/types" + migrationkeeper "github.com/pokt-network/poktroll/x/migration/keeper" + migrationtypes "github.com/pokt-network/poktroll/x/migration/types" proofkeeper "github.com/pokt-network/poktroll/x/proof/keeper" prooftypes "github.com/pokt-network/poktroll/x/proof/types" servicekeeper "github.com/pokt-network/poktroll/x/service/keeper" @@ -67,6 +69,7 @@ type TokenomicsModuleKeepers struct { tokenomicstypes.SharedKeeper tokenomicstypes.SessionKeeper tokenomicstypes.ServiceKeeper + tokenomicstypes.MigrationKeeper Codec *codec.ProtoCodec } @@ -324,6 +327,7 @@ func NewTokenomicsModuleKeepers( prooftypes.StoreKey, sharedtypes.StoreKey, servicetypes.StoreKey, + migrationtypes.StoreKey, ) // Construct a multistore & mount store keys for each keeper that will interact with the state store. @@ -523,6 +527,22 @@ func NewTokenomicsModuleKeepers( require.NoError(t, err) } + migrationKeeper := migrationkeeper.NewKeeper( + cdc, + runtime.NewKVStoreService(keys[migrationtypes.StoreKey]), + logger, + authority.String(), + accountKeeper, + bankKeeper, + ) + + require.NoError(t, migrationKeeper.SetParams(sdkCtx, migrationtypes.DefaultParams())) + + if params, ok := cfg.moduleParams[migrationtypes.ModuleName]; ok { + err := migrationKeeper.SetParams(ctx, *params.(*migrationtypes.Params)) + require.NoError(t, err) + } + keepers := TokenomicsModuleKeepers{ Keeper: &tokenomicsKeeper, AccountKeeper: &accountKeeper, @@ -533,6 +553,7 @@ func NewTokenomicsModuleKeepers( SharedKeeper: &sharedKeeper, SessionKeeper: &sessionKeeper, ServiceKeeper: &serviceKeeper, + MigrationKeeper: &migrationKeeper, Codec: cdc, } diff --git a/testutil/testmigration/fixtures.go b/testutil/testmigration/fixtures.go index b77a34a1f..23b073cf8 100644 --- a/testutil/testmigration/fixtures.go +++ b/testutil/testmigration/fixtures.go @@ -3,7 +3,6 @@ package testmigration import ( "encoding/binary" "fmt" - "math/rand" cometcrypto "github.com/cometbft/cometbft/crypto/ed25519" cmtjson "github.com/cometbft/cometbft/libs/json" @@ -69,10 +68,7 @@ func NewMorseStateExportAndAccountState( } for i := 1; i < numAccounts+1; i++ { - seedUint := rand.Uint64() - seedBz := make([]byte, 8) - binary.LittleEndian.PutUint64(seedBz, seedUint) - privKey := cometcrypto.GenPrivKeyFromSecret(seedBz) + privKey := NewMorsePrivateKey(t, uint64(i)) pubKey := privKey.PubKey() balanceAmount := int64(1e6*i + i) // i_000_00i appStakeAmount := int64(1e5*i + (i * 10)) // i00_0i0 @@ -120,12 +116,24 @@ func NewMorseStateExportAndAccountState( // Add the account to the morseAccountState. morseAccountState.Accounts[i-1] = &migrationtypes.MorseClaimableAccount{ MorseSrcAddress: pubKey.Address().String(), + PublicKey: pubKey.Bytes(), UnstakedBalance: cosmostypes.NewInt64Coin(volatile.DenomuPOKT, balanceAmount), SupplierStake: cosmostypes.NewInt64Coin(volatile.DenomuPOKT, supplierStakeAmount), ApplicationStake: cosmostypes.NewInt64Coin(volatile.DenomuPOKT, appStakeAmount), - PublicKey: pubKey.Bytes(), + // ShannonDestAddress: (intentionally omitted). + // ClaimedAtHeight: (intentionally omitted) } } return morseStateExport, morseAccountState } + +// NewMorsePrivateKey creates a new ed25519 private key from the given seed. +func NewMorsePrivateKey(t gocuke.TestingT, seed uint64) cometcrypto.PrivKey { + t.Helper() + + seedBz := make([]byte, 8) + binary.LittleEndian.PutUint64(seedBz, seed) + + return cometcrypto.GenPrivKeyFromSecret(seedBz) +} diff --git a/x/tokenomics/types/expected_keepers.go b/x/tokenomics/types/expected_keepers.go index ba26ae4fa..13b62cbdf 100644 --- a/x/tokenomics/types/expected_keepers.go +++ b/x/tokenomics/types/expected_keepers.go @@ -9,6 +9,7 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" apptypes "github.com/pokt-network/poktroll/x/application/types" + migrationtypes "github.com/pokt-network/poktroll/x/migration/types" prooftypes "github.com/pokt-network/poktroll/x/proof/types" servicetypes "github.com/pokt-network/poktroll/x/service/types" sessiontypes "github.com/pokt-network/poktroll/x/session/types" @@ -98,3 +99,9 @@ type ServiceKeeper interface { GetParams(ctx context.Context) servicetypes.Params SetParams(ctx context.Context, params servicetypes.Params) error } + +type MigrationKeeper interface { + ImportFromMorseAccountState(ctx context.Context, morseAccountState *migrationtypes.MorseAccountState) + GetMorseClaimableAccount(ctx context.Context, morseHexAddress string) (morseAccount migrationtypes.MorseClaimableAccount, isFound bool) + GetAllMorseClaimableAccounts(ctx context.Context) (morseAccounts []migrationtypes.MorseClaimableAccount) +} From 8e1a53378af2c4f1ece8950f1a4d23c28920828f Mon Sep 17 00:00:00 2001 From: Bryan White Date: Tue, 18 Feb 2025 11:23:01 +0100 Subject: [PATCH 07/18] chore: add migration module mocks pkg --- Makefile | 1 + testutil/migration/mocks/mocks.go | 11 +++++++++++ x/migration/types/expected_keepers.go | 2 ++ 3 files changed, 14 insertions(+) create mode 100644 testutil/migration/mocks/mocks.go diff --git a/Makefile b/Makefile index 75fbe43c5..d2fd54e48 100644 --- a/Makefile +++ b/Makefile @@ -201,6 +201,7 @@ go_mockgen: ## Use `mockgen` to generate mocks used for testing purposes of all go generate ./x/service/types/ go generate ./x/proof/types/ go generate ./x/tokenomics/types/ + go generate ./x/migration/types/ find . -name interface.go | xargs -I {} go generate {} .PHONY: go_testgen_fixtures diff --git a/testutil/migration/mocks/mocks.go b/testutil/migration/mocks/mocks.go new file mode 100644 index 000000000..595954e65 --- /dev/null +++ b/testutil/migration/mocks/mocks.go @@ -0,0 +1,11 @@ +package mocks + +// This file is in place to declare the package for dynamically generated structs. +// +// Note that this does not follow the Cosmos SDK pattern of committing Mocks to main. +// For example, they commit auto-generate code to main: https://github.com/cosmos/cosmos-sdk/blob/main/x/gov/testutil/expected_keepers_mocks.go +// Documentation on how Cosmos uses mockgen can be found here: https://docs.cosmos.network/main/build/building-modules/testing#unit-tests +// +// IMPORTANT: We have attempted to use `.gitkeep` files instead, but it causes a circular dependency issue with protobuf and mock generation +// since we are leveraging `ignite` to compile `.proto` files which runs `go mod tidy` before generating, requiring the entire dependency tree +// to be valid before mock implementations have been generated. diff --git a/x/migration/types/expected_keepers.go b/x/migration/types/expected_keepers.go index 3902ed53a..64aa3a3e3 100644 --- a/x/migration/types/expected_keepers.go +++ b/x/migration/types/expected_keepers.go @@ -1,3 +1,5 @@ +//go:generate go run go.uber.org/mock/mockgen -destination ../../../testutil/migration/mocks/expected_keepers_mock.go -package mocks . AccountKeeper,BankKeeper + package types import ( From 93004e6bc732dfcbdd3dcb75ad655ea9ba6db845 Mon Sep 17 00:00:00 2001 From: Bryan White Date: Tue, 18 Feb 2025 11:26:42 +0100 Subject: [PATCH 08/18] chore: validation, testing, etc. --- .../morse_account_import_and_claim_test.go | 16 +- x/migration/keeper/morse_claimable_account.go | 3 + .../keeper/msg_server_claim_morse_account.go | 53 ++--- .../msg_server_claim_morse_acount_test.go | 188 ++++++++++++++++-- ..._server_import_morse_claimable_accounts.go | 2 +- ...er_import_morse_claimable_accounts_test.go | 3 + x/migration/types/errors.go | 8 +- .../types/message_claim_morse_account.go | 10 +- .../types/message_claim_morse_account_test.go | 24 ++- ...message_import_morse_claimable_accounts.go | 4 +- ...ge_import_morse_claimable_accounts_test.go | 2 +- x/migration/types/types.go | 5 + 12 files changed, 249 insertions(+), 69 deletions(-) diff --git a/tests/integration/migration/morse_account_import_and_claim_test.go b/tests/integration/migration/morse_account_import_and_claim_test.go index 6d7715f50..9143c38cc 100644 --- a/tests/integration/migration/morse_account_import_and_claim_test.go +++ b/tests/integration/migration/morse_account_import_and_claim_test.go @@ -64,12 +64,12 @@ func TestMsgServer_CreateMorseAccountClaim(t *testing.T) { require.Equal(t, int64(0), shannonDestBalance.Amount.Int64()) morsePrivateKey := testmigration.NewMorsePrivateKey(t, 1) - morseDestAddr := morsePrivateKey.PubKey().Address().String() - require.Equal(t, morseDestAddr, accountState.Accounts[0].MorseSrcAddress) + morseSrcAddr := morsePrivateKey.PubKey().Address().String() + require.Equal(t, morseSrcAddr, accountState.Accounts[0].MorseSrcAddress) morseClaimMsg, err := migrationtypes.NewMsgClaimMorseAccount( shannonDestAddr, - morseDestAddr, + morseSrcAddr, morsePrivateKey, ) require.NoError(t, err) @@ -80,7 +80,7 @@ func TestMsgServer_CreateMorseAccountClaim(t *testing.T) { expectedBalance := sdk.NewInt64Coin(volatile.DenomuPOKT, 1110111) expectedClaimAccountRes := &migrationtypes.MsgClaimMorseAccountResponse{ - MorseSrcAddress: morseDestAddr, + MorseSrcAddress: morseSrcAddr, ClaimedBalance: expectedBalance, ClaimedAtHeight: app.GetSdkCtx().BlockHeight() - 1, } @@ -90,13 +90,15 @@ func TestMsgServer_CreateMorseAccountClaim(t *testing.T) { require.Equal(t, expectedClaimAccountRes, claimAccountRes) // Assert that the MorseClaimableAccount was updated on-chain. - expectedMorseClaimableAccount := accountState.Accounts[0] + expectedMorseClaimableAccount := *accountState.Accounts[0] + expectedMorseClaimableAccount.ClaimedAtHeight = app.GetSdkCtx().BlockHeight() - 1 + morseAccountQuerier := migrationtypes.NewQueryClient(app.QueryHelper()) morseClaimableAcctRes, err := morseAccountQuerier.MorseClaimableAccount(app.GetSdkCtx(), &migrationtypes.QueryGetMorseClaimableAccountRequest{ - Address: morseDestAddr, + Address: morseSrcAddr, }) require.NoError(t, err) - require.Equal(t, *expectedMorseClaimableAccount, morseClaimableAcctRes.MorseClaimableAccount) + require.Equal(t, expectedMorseClaimableAccount, morseClaimableAcctRes.MorseClaimableAccount) // Assert that the shannonDestAddr account balance has been updated. shannonDestBalance, err = bankClient.GetBalance(app.GetSdkCtx(), shannonDestAddr) diff --git a/x/migration/keeper/morse_claimable_account.go b/x/migration/keeper/morse_claimable_account.go index 5cdf1cc51..dd3e3e43a 100644 --- a/x/migration/keeper/morse_claimable_account.go +++ b/x/migration/keeper/morse_claimable_account.go @@ -72,11 +72,14 @@ func (k Keeper) GetAllMorseClaimableAccounts(ctx context.Context) (list []types. // ImportFromMorseAccountState imports the MorseClaimableAccounts from the given MorseAccountState. // It returns the state hash of the imported MorseAccountState. +// DEV_NOTE: It assumes that the MorseAccountState has already been validated. func (k Keeper) ImportFromMorseAccountState( ctx context.Context, morseAccountState *types.MorseAccountState, ) { for _, morseAccount := range morseAccountState.Accounts { + // DEV_NOTE: Ensure all MorseClaimableAccounts are initially unclaimed. + morseAccount.ClaimedAtHeight = 0 k.SetMorseClaimableAccount(ctx, *morseAccount) } } diff --git a/x/migration/keeper/msg_server_claim_morse_account.go b/x/migration/keeper/msg_server_claim_morse_account.go index 7aca9d728..0035ed266 100644 --- a/x/migration/keeper/msg_server_claim_morse_account.go +++ b/x/migration/keeper/msg_server_claim_morse_account.go @@ -15,10 +15,7 @@ func (k msgServer) ClaimMorseAccount(ctx context.Context, msg *migrationtypes.Ms sdkCtx := cosmostypes.UnwrapSDKContext(ctx) if err := msg.ValidateBasic(); err != nil { - return nil, status.Error( - codes.InvalidArgument, - migrationtypes.ErrMorseClaimableAccount.Wrap(err.Error()).Error(), - ) + return nil, status.Error(codes.InvalidArgument, err.Error()) } shannonAccAddr, err := cosmostypes.AccAddressFromBech32(msg.ShannonDestAddress) @@ -34,41 +31,51 @@ func (k msgServer) ClaimMorseAccount(ctx context.Context, msg *migrationtypes.Ms ) } - // Ensure that a claim for the given morseSrcAddress does not already exist. - morseAccountClaim, isFound := k.GetMorseClaimableAccount( + // Ensure that a MorseClaimableAccount exists for the given morseSrcAddress. + morseClaimableAccount, isFound := k.GetMorseClaimableAccount( sdkCtx, msg.MorseSrcAddress, ) if !isFound { return nil, status.Error( codes.NotFound, - migrationtypes.ErrMorseClaimableAccount.Wrapf( + migrationtypes.ErrMorseAccountClaim.Wrapf( "no morse claimable account exists with address %q", msg.MorseSrcAddress, ).Error(), ) } + // Ensure that the given MorseClaimableAccount has not already been claimed. + if morseClaimableAccount.ClaimedAtHeight > 0 || + morseClaimableAccount.ShannonDestAddress != "" { + return nil, status.Error( + codes.FailedPrecondition, + migrationtypes.ErrMorseAccountClaim.Wrapf( + "morse address %q has already been claimed at height %d by shannon address %q", + msg.MorseSrcAddress, + morseClaimableAccount.ClaimedAtHeight, + morseClaimableAccount.ShannonDestAddress, + ).Error(), + ) + } + + // Update the MorseClaimableAccount + morseClaimableAccount.ClaimedAtHeight = sdkCtx.BlockHeight() k.SetMorseClaimableAccount( sdkCtx, - morseAccountClaim, + morseClaimableAccount, ) // Add any actor stakes to the account balance because we're not creating // a shannon actor (i.e. not a re-stake claim). - totalTokens := morseAccountClaim.UnstakedBalance. - Add(morseAccountClaim.ApplicationStake). - Add(morseAccountClaim.SupplierStake) + totalTokens := morseClaimableAccount.UnstakedBalance. + Add(morseClaimableAccount.ApplicationStake). + Add(morseClaimableAccount.SupplierStake) // Mint the sum of the account balance (totalTokens) and any actor stakes to the migration module account. if err = k.bankKeeper.MintCoins(ctx, migrationtypes.ModuleName, cosmostypes.NewCoins(totalTokens)); err != nil { - return nil, status.Error( - codes.Internal, - migrationtypes.ErrMorseClaimableAccount.Wrapf( - "failed to mint coins: %v", - err, - ).Error(), - ) + return nil, status.Error(codes.Internal, err.Error()) } // Transfer the totalTokens to the shannonDestAddress account. @@ -77,13 +84,7 @@ func (k msgServer) ClaimMorseAccount(ctx context.Context, msg *migrationtypes.Ms shannonAccAddr, cosmostypes.NewCoins(totalTokens), ); err != nil { - return nil, status.Error( - codes.Internal, - migrationtypes.ErrMorseClaimableAccount.Wrapf( - "failed to send coins: %v", - err, - ).Error(), - ) + return nil, status.Error(codes.Internal, err.Error()) } // Emit an event which signals that the morse account has been claimed. @@ -96,7 +97,7 @@ func (k msgServer) ClaimMorseAccount(ctx context.Context, msg *migrationtypes.Ms if err = sdkCtx.EventManager().EmitTypedEvent(&event); err != nil { return nil, status.Error( codes.Internal, - migrationtypes.ErrMorseClaimableAccount.Wrapf( + migrationtypes.ErrMorseAccountClaim.Wrapf( "failed to emit event type %T: %v", &event, err, diff --git a/x/migration/keeper/msg_server_claim_morse_acount_test.go b/x/migration/keeper/msg_server_claim_morse_acount_test.go index 6b38a1e41..736d12544 100644 --- a/x/migration/keeper/msg_server_claim_morse_acount_test.go +++ b/x/migration/keeper/msg_server_claim_morse_acount_test.go @@ -5,45 +5,189 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" - "github.com/pokt-network/poktroll/app/volatile" + "github.com/pokt-network/poktroll/testutil/events" keepertest "github.com/pokt-network/poktroll/testutil/keeper" "github.com/pokt-network/poktroll/testutil/sample" + "github.com/pokt-network/poktroll/testutil/testmigration" "github.com/pokt-network/poktroll/x/migration/keeper" - "github.com/pokt-network/poktroll/x/migration/types" + migrationtypes "github.com/pokt-network/poktroll/x/migration/types" ) // Prevent strconv unused error var _ = strconv.IntSize -func TestMorseAccountClaimMsgServerCreate(t *testing.T) { +func TestMsgServer_ClaimMorseAccount_Success(t *testing.T) { k, ctx := keepertest.MigrationKeeper(t) srv := keeper.NewMsgServerImpl(k) - for i := 0; i < 5; i++ { - msgClaim := &types.MsgClaimMorseAccount{ - ShannonDestAddress: sample.AccAddress(), - MorseSrcAddress: sample.MorseAddressHex(), - } - _, err := srv.ClaimMorseAccount(ctx, msgClaim) - require.NoError(t, err) - rst, found := k.GetMorseClaimableAccount(ctx, - msgClaim.MorseSrcAddress, + + // Generate and import Morse claimable accounts. + numAccounts := 6 + _, accountState := testmigration.NewMorseStateExportAndAccountState(t, numAccounts) + accountStateHash, err := accountState.GetHash() + require.NoError(t, err) + + _, err = srv.ImportMorseClaimableAccounts(ctx, &migrationtypes.MsgImportMorseClaimableAccounts{ + Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(), + MorseAccountState: *accountState, + MorseAccountStateHash: accountStateHash, + }) + require.NoError(t, err) + + // Claim each MorseClaimableAccount. + for morseAccountIdx, morseAccount := range accountState.Accounts { + // Generate the corresponding morse private key using the account slice index as a seed. + morsePrivKey := testmigration.NewMorsePrivateKey(t, uint64(morseAccountIdx)) + + // Claim the MorseClaimableAccount. + msgClaim, err := migrationtypes.NewMsgClaimMorseAccount( + sample.AccAddress(), + morseAccount.GetMorseSrcAddress(), + morsePrivKey, ) - require.True(t, found) + require.NoError(t, err) + + msgClaimRes, err := srv.ClaimMorseAccount(ctx, msgClaim) + require.NoError(t, err) - expectedRes := &types.MsgClaimMorseAccountResponse{ + // Construct and assert the expected response. + expectedClaimedBalance := morseAccount.GetUnstakedBalance(). + Add(morseAccount.GetSupplierStake()). + Add(morseAccount.GetApplicationStake()) + expectedRes := &migrationtypes.MsgClaimMorseAccountResponse{ MorseSrcAddress: msgClaim.MorseSrcAddress, - ClaimedBalance: sdk.NewInt64Coin(volatile.DenomuPOKT, 0), - ClaimedAtHeight: 0, + ClaimedBalance: expectedClaimedBalance, + ClaimedAtHeight: ctx.BlockHeight(), + } + require.Equal(t, expectedRes, msgClaimRes) + + // Assert that the persisted MorseClaimableAccount is updated. + expectedMorseAccount := morseAccount + expectedMorseAccount.ClaimedAtHeight = ctx.BlockHeight() + foundMorseAccount, found := k.GetMorseClaimableAccount(ctx, msgClaim.MorseSrcAddress) + require.True(t, found) + require.Equal(t, *expectedMorseAccount, foundMorseAccount) + + // Assert that an event is emitted for each claim. + expectedEvent := &migrationtypes.EventMorseAccountClaimed{ + ShannonDestAddress: msgClaim.ShannonDestAddress, + MorseSrcAddress: msgClaim.MorseSrcAddress, + ClaimedBalance: expectedClaimedBalance, + ClaimedAtHeight: ctx.BlockHeight(), } - require.Equal(t, expectedRes, rst) + claimEvents := events.FilterEvents[*migrationtypes.EventMorseAccountClaimed](t, ctx.EventManager().Events()) + require.Equal(t, 1, len(claimEvents)) + require.Equal(t, expectedEvent, claimEvents[0]) - // assert each event was emitted... - // assert that the morse account was clamed... + // Reset the event manager to isolate events between claims. + ctx = ctx.WithEventManager(sdk.NewEventManager()) } } -// TODO_IN_THIS_COMMIT: error cases... -// - invalid ValidateBasic() -// - MorseClaimableAccount not found +func TestMsgServer_ClaimMorseAccount_Error(t *testing.T) { + k, ctx := keepertest.MigrationKeeper(t) + srv := keeper.NewMsgServerImpl(k) + + // Generate and import a Morse claimable account. + numAccounts := 1 + _, accountState := testmigration.NewMorseStateExportAndAccountState(t, numAccounts) + accountStateHash, err := accountState.GetHash() + require.NoError(t, err) + + _, err = srv.ImportMorseClaimableAccounts(ctx, &migrationtypes.MsgImportMorseClaimableAccounts{ + Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(), + MorseAccountState: *accountState, + MorseAccountStateHash: accountStateHash, + }) + require.NoError(t, err) + + // Generate the corresponding morse private key using the account slice index as a seed. + morsePrivKey := testmigration.NewMorsePrivateKey(t, 0) + + // Claim the MorseClaimableAccount with a random Shannon address. + msgClaim, err := migrationtypes.NewMsgClaimMorseAccount( + sample.AccAddress(), + accountState.Accounts[0].GetMorseSrcAddress(), + morsePrivKey, + ) + require.NoError(t, err) + + t.Run("invalid claim msg", func(t *testing.T) { + // Copy the message and set the morse signature to an empty string. + invalidMsgClaim := *msgClaim + invalidMsgClaim.MorseSignature = "" + + expectedErr := status.Error( + codes.InvalidArgument, + migrationtypes.ErrMorseAccountClaim.Wrapf( + "morseSignature is empty", + ).Error(), + ) + + _, err := srv.ClaimMorseAccount(ctx, &invalidMsgClaim) + require.EqualError(t, err, expectedErr.Error()) + }) + + t.Run("account not found", func(t *testing.T) { + // Copy the message and set the morse src address to a valid but incorrect address. + invalidMsgClaim := *msgClaim + invalidMsgClaim.MorseSrcAddress = sample.MorseAddressHex() + + expectedErr := status.Error( + codes.NotFound, + migrationtypes.ErrMorseAccountClaim.Wrapf( + "no morse claimable account exists with address %q", + invalidMsgClaim.GetMorseSrcAddress(), + ).Error(), + ) + + _, err := srv.ClaimMorseAccount(ctx, &invalidMsgClaim) + require.EqualError(t, err, expectedErr.Error()) + }) + + t.Run("account already claimed (non-zero claimed_at_height)", func(t *testing.T) { + // Set the claimed at height BUT NOT the Shannon destination address. + morseClaimableAccount := *accountState.Accounts[0] + morseClaimableAccount.ClaimedAtHeight = 10 + k.SetMorseClaimableAccount(ctx, morseClaimableAccount) + + expectedErr := status.Error( + codes.FailedPrecondition, + migrationtypes.ErrMorseAccountClaim.Wrapf( + "morse address %q has already been claimed at height %d by shannon address %q", + accountState.Accounts[0].GetMorseSrcAddress(), + 10, + accountState.Accounts[0].GetShannonDestAddress(), + ).Error(), + ) + + _, err := srv.ClaimMorseAccount(ctx, msgClaim) + require.EqualError(t, err, expectedErr.Error()) + }) + + t.Run("account already claimed (non-empty shannon_dest_address)", func(t *testing.T) { + // Set the Shannon destination address BUT NOT the claimed at height. + morseClaimableAccount := *accountState.Accounts[0] + morseClaimableAccount.ClaimedAtHeight = 0 + morseClaimableAccount.ShannonDestAddress = sample.AccAddress() + k.SetMorseClaimableAccount(ctx, morseClaimableAccount) + + expectedErr := status.Error( + codes.FailedPrecondition, + migrationtypes.ErrMorseAccountClaim.Wrapf( + "morse address %q has already been claimed at height %d by shannon address %q", + accountState.Accounts[0].GetMorseSrcAddress(), + 0, + morseClaimableAccount.ShannonDestAddress, + ).Error(), + ) + + _, err := srv.ClaimMorseAccount(ctx, msgClaim) + require.EqualError(t, err, expectedErr.Error()) + }) +} diff --git a/x/migration/keeper/msg_server_import_morse_claimable_accounts.go b/x/migration/keeper/msg_server_import_morse_claimable_accounts.go index dcc093b2f..5671b5ca2 100644 --- a/x/migration/keeper/msg_server_import_morse_claimable_accounts.go +++ b/x/migration/keeper/msg_server_import_morse_claimable_accounts.go @@ -27,7 +27,7 @@ func (k msgServer) ImportMorseClaimableAccounts(ctx context.Context, msg *migrat // Check if MorseClaimableAccounts have already been imported. if morseClaimableAccounts := k.GetAllMorseClaimableAccounts(sdkCtx); len(morseClaimableAccounts) > 0 { - err := migrationtypes.ErrMorseAccountState.Wrap("Morse claimable accounts already imported") + err := migrationtypes.ErrMorseAccountsImport.Wrap("Morse claimable accounts already imported") logger.Info(err.Error()) return nil, status.Error(codes.FailedPrecondition, err.Error()) } diff --git a/x/migration/keeper/msg_server_import_morse_claimable_accounts_test.go b/x/migration/keeper/msg_server_import_morse_claimable_accounts_test.go index f0b3c7800..6e21625c0 100644 --- a/x/migration/keeper/msg_server_import_morse_claimable_accounts_test.go +++ b/x/migration/keeper/msg_server_import_morse_claimable_accounts_test.go @@ -118,3 +118,6 @@ func TestMsgServer_ImportMorseClaimableAccounts_ErrorInvalidAuthority(t *testing require.Equal(t, codes.PermissionDenied, stat.Code()) require.ErrorContains(t, err, "invalid authority address") } + +// TODO_IN_THIS_COMMIT: Test an import with non-zero ClaimedAtHeight for one or +// more accounts; the heights SHOULD be reset to 0 when persisted. diff --git a/x/migration/types/errors.go b/x/migration/types/errors.go index c5f3f5bd8..f1d42ecbe 100644 --- a/x/migration/types/errors.go +++ b/x/migration/types/errors.go @@ -8,8 +8,8 @@ import ( // x/migration module sentinel errors var ( - ErrInvalidSigner = sdkerrors.Register(ModuleName, 1100, "expected gov account as only signer for proposal message") - ErrMorseAccountState = sdkerrors.Register(ModuleName, 1101, "morse account state is invalid") - ErrUnauthorized = sdkerrors.Register(ModuleName, 1102, "unauthorized") - ErrMorseClaimableAccount = sdkerrors.Register(ModuleName, 1103, "morse claimable account is invalid") + ErrInvalidSigner = sdkerrors.Register(ModuleName, 1100, "expected gov account as only signer for proposal message") + ErrMorseAccountsImport = sdkerrors.Register(ModuleName, 1101, "unable to import morse claimable accounts") + ErrUnauthorized = sdkerrors.Register(ModuleName, 1102, "unauthorized") + ErrMorseAccountClaim = sdkerrors.Register(ModuleName, 1103, "unable to claim morse account") ) diff --git a/x/migration/types/message_claim_morse_account.go b/x/migration/types/message_claim_morse_account.go index 261a3b0ae..911286226 100644 --- a/x/migration/types/message_claim_morse_account.go +++ b/x/migration/types/message_claim_morse_account.go @@ -33,11 +33,15 @@ func NewMsgClaimMorseAccount( } func (msg *MsgClaimMorseAccount) ValidateBasic() error { + if len(msg.MorseSignature) == 0 { + return ErrMorseAccountClaim.Wrap("morseSignature is empty") + } - // TODO_UPNEXT(@bryanchriswhite#1034): Add validation + if len(msg.MorseSrcAddress) != MorseAddressHexLengthBytes { + return ErrMorseAccountClaim.Wrapf("invalid morseSrcAddress length (%d)", len(msg.MorseSrcAddress)) + } - _, err := sdk.AccAddressFromBech32(msg.ShannonDestAddress) - if err != nil { + if _, err := sdk.AccAddressFromBech32(msg.ShannonDestAddress); err != nil { return errorsmod.Wrapf(sdkerrors.ErrInvalidAddress, "invalid shannonDestAddress address (%s)", err) } return nil diff --git a/x/migration/types/message_claim_morse_account_test.go b/x/migration/types/message_claim_morse_account_test.go index 83ca6ac00..8f16b77f6 100644 --- a/x/migration/types/message_claim_morse_account_test.go +++ b/x/migration/types/message_claim_morse_account_test.go @@ -4,8 +4,9 @@ import ( "testing" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/pokt-network/poktroll/testutil/sample" "github.com/stretchr/testify/require" + + "github.com/pokt-network/poktroll/testutil/sample" ) func TestMsgClaimMorseAccount_ValidateBasic(t *testing.T) { @@ -15,15 +16,27 @@ func TestMsgClaimMorseAccount_ValidateBasic(t *testing.T) { err error }{ { - name: "invalid address", + name: "invalid ShannonDestAddress", msg: MsgClaimMorseAccount{ ShannonDestAddress: "invalid_address", + MorseSrcAddress: sample.MorseAddressHex(), + MorseSignature: "mock_signature", }, err: sdkerrors.ErrInvalidAddress, }, { - name: "valid address", + name: "invalid MorseSrcAddress", + msg: MsgClaimMorseAccount{ + ShannonDestAddress: sample.AccAddress(), + MorseSrcAddress: "invalid_address", + MorseSignature: "mock_signature", + }, + err: ErrMorseAccountClaim, + }, { + name: "valid claim message", msg: MsgClaimMorseAccount{ ShannonDestAddress: sample.AccAddress(), + MorseSrcAddress: sample.MorseAddressHex(), + MorseSignature: "mock_signature", }, }, } @@ -38,3 +51,8 @@ func TestMsgClaimMorseAccount_ValidateBasic(t *testing.T) { }) } } + +// TODO_IN_THIS_COMMIT: error cases... +// - empty signature +// - invalid length morse hex addr +// - invalid shannon bech32 addr diff --git a/x/migration/types/message_import_morse_claimable_accounts.go b/x/migration/types/message_import_morse_claimable_accounts.go index cba065608..d66bd5ee6 100644 --- a/x/migration/types/message_import_morse_claimable_accounts.go +++ b/x/migration/types/message_import_morse_claimable_accounts.go @@ -37,11 +37,11 @@ func (msg *MsgImportMorseClaimableAccounts) ValidateBasic() error { expectedHash := msg.GetMorseAccountStateHash() if len(expectedHash) == 0 { - return ErrMorseAccountState.Wrapf("expected hash is empty") + return ErrMorseAccountsImport.Wrapf("expected hash is empty") } if !bytes.Equal(actualHash, expectedHash) { - return ErrMorseAccountState.Wrapf( + return ErrMorseAccountsImport.Wrapf( "Morse account state hash (%x) doesn't match expected: (%x)", actualHash, expectedHash, ) diff --git a/x/migration/types/message_import_morse_claimable_accounts_test.go b/x/migration/types/message_import_morse_claimable_accounts_test.go index fdf6fae60..74a2a69b7 100644 --- a/x/migration/types/message_import_morse_claimable_accounts_test.go +++ b/x/migration/types/message_import_morse_claimable_accounts_test.go @@ -31,7 +31,7 @@ func TestMsgImportMorseClaimableAccounts_ValidateBasic(t *testing.T) { { name: "invalid morse account state hash", msg: invalidMsg, - err: ErrMorseAccountState, + err: ErrMorseAccountsImport, }, { name: "valid address", diff --git a/x/migration/types/types.go b/x/migration/types/types.go index ab1254f4c..00efae8db 100644 --- a/x/migration/types/types.go +++ b/x/migration/types/types.go @@ -1 +1,6 @@ package types + +const ( + MorseAddressLengthBytes = 20 + MorseAddressHexLengthBytes = MorseAddressLengthBytes * 2 +) From 0848fb14707d546ca4cd6c9c59ae044197a0df8a Mon Sep 17 00:00:00 2001 From: Bryan White Date: Tue, 18 Feb 2025 11:30:51 +0100 Subject: [PATCH 09/18] chore: self-review improvements --- api/poktroll/migration/event.pulsar.go | 4 ++-- proto/poktroll/migration/event.proto | 2 +- .../migration/morse_account_import_and_claim_test.go | 6 ------ ...msg_server_import_morse_claimable_accounts_test.go | 11 ++++++----- x/migration/types/event.pb.go | 2 +- x/migration/types/message_claim_morse_account.go | 4 ++++ x/migration/types/message_claim_morse_account_test.go | 5 ----- 7 files changed, 14 insertions(+), 20 deletions(-) diff --git a/api/poktroll/migration/event.pulsar.go b/api/poktroll/migration/event.pulsar.go index 603c1b800..ec5f9587d 100644 --- a/api/poktroll/migration/event.pulsar.go +++ b/api/poktroll/migration/event.pulsar.go @@ -3,11 +3,11 @@ package migration import ( v1beta1 "cosmossdk.io/api/cosmos/base/v1beta1" + _ "github.com/pokt-network/poktroll/api/poktroll/shared" fmt "fmt" _ "github.com/cosmos/cosmos-proto" runtime "github.com/cosmos/cosmos-proto/runtime" _ "github.com/cosmos/gogoproto/gogoproto" - _ "github.com/pokt-network/poktroll/api/poktroll/shared" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoiface "google.golang.org/protobuf/runtime/protoiface" protoimpl "google.golang.org/protobuf/runtime/protoimpl" @@ -1214,7 +1214,7 @@ func (x *EventImportMorseClaimableAccounts) GetNumAccounts() uint64 { return 0 } -// TODO_IN_THIS_COMMIT: comments... +// EventMorseAccountClaimed is emitted when a MorseAccount is claimed on-chain. type EventMorseAccountClaimed struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache diff --git a/proto/poktroll/migration/event.proto b/proto/poktroll/migration/event.proto index 3c109c4da..1f7caa0d4 100644 --- a/proto/poktroll/migration/event.proto +++ b/proto/poktroll/migration/event.proto @@ -24,7 +24,7 @@ message EventImportMorseClaimableAccounts { uint64 num_accounts = 3 [(gogoproto.jsontag) = "num_accounts"]; } -// TODO_IN_THIS_COMMIT: comments... +// EventMorseAccountClaimed is emitted when a MorseAccount is claimed on-chain. message EventMorseAccountClaimed { // The height (on Shannon) at which the claim was executed (i.e. claimed). int64 claimed_at_height = 1 [(gogoproto.jsontag) = "claimed_at_height"]; diff --git a/tests/integration/migration/morse_account_import_and_claim_test.go b/tests/integration/migration/morse_account_import_and_claim_test.go index 9143c38cc..64daf7630 100644 --- a/tests/integration/migration/morse_account_import_and_claim_test.go +++ b/tests/integration/migration/morse_account_import_and_claim_test.go @@ -11,7 +11,6 @@ import ( "github.com/stretchr/testify/require" "github.com/pokt-network/poktroll/app/volatile" - "github.com/pokt-network/poktroll/cmd/poktrolld/cmd" "github.com/pokt-network/poktroll/pkg/client/query" "github.com/pokt-network/poktroll/testutil/integration" "github.com/pokt-network/poktroll/testutil/sample" @@ -19,11 +18,6 @@ import ( migrationtypes "github.com/pokt-network/poktroll/x/migration/types" ) -// TODO_IN_THIS_COMMIT: confirm whether this is necessary... -func init() { - cmd.InitSDKConfig() -} - func TestMsgServer_CreateMorseAccountClaim(t *testing.T) { app := integration.NewCompleteIntegrationApp(t) diff --git a/x/migration/keeper/msg_server_import_morse_claimable_accounts_test.go b/x/migration/keeper/msg_server_import_morse_claimable_accounts_test.go index 6e21625c0..294057a76 100644 --- a/x/migration/keeper/msg_server_import_morse_claimable_accounts_test.go +++ b/x/migration/keeper/msg_server_import_morse_claimable_accounts_test.go @@ -83,9 +83,13 @@ func TestMsgServer_ImportMorseClaimableAccounts_ErrorAlreadySet(t *testing.T) { _, accountState := testmigration.NewMorseStateExportAndAccountState(t, numAccounts) k.ImportFromMorseAccountState(ctx, accountState) - // Assert that the MorseAccountState have been set. + // Assert that the MorseClaimableAccounts are persisted AND unclaimed. morseClaimableAccounts = k.GetAllMorseClaimableAccounts(ctx) - require.Equal(t, 10, len(morseClaimableAccounts)) + require.Equal(t, numAccounts, len(morseClaimableAccounts)) + for _, morseClaimableAccount := range morseClaimableAccounts { + require.Equal(t, int64(0), morseClaimableAccount.ClaimedAtHeight) + require.Equal(t, "", morseClaimableAccount.ShannonDestAddress) + } // Assert that the MorseAccountState can ONLY be set once. msgImportMorseClaimableAccounts, err := migrationtypes.NewMsgImportMorseClaimableAccounts( @@ -118,6 +122,3 @@ func TestMsgServer_ImportMorseClaimableAccounts_ErrorInvalidAuthority(t *testing require.Equal(t, codes.PermissionDenied, stat.Code()) require.ErrorContains(t, err, "invalid authority address") } - -// TODO_IN_THIS_COMMIT: Test an import with non-zero ClaimedAtHeight for one or -// more accounts; the heights SHOULD be reset to 0 when persisted. diff --git a/x/migration/types/event.pb.go b/x/migration/types/event.pb.go index 456a5b509..1aee62c40 100644 --- a/x/migration/types/event.pb.go +++ b/x/migration/types/event.pb.go @@ -87,7 +87,7 @@ func (m *EventImportMorseClaimableAccounts) GetNumAccounts() uint64 { return 0 } -// TODO_IN_THIS_COMMIT: comments... +// EventMorseAccountClaimed is emitted when a MorseAccount is claimed on-chain. type EventMorseAccountClaimed struct { // The height (on Shannon) at which the claim was executed (i.e. claimed). ClaimedAtHeight int64 `protobuf:"varint,1,opt,name=claimed_at_height,json=claimedAtHeight,proto3" json:"claimed_at_height"` diff --git a/x/migration/types/message_claim_morse_account.go b/x/migration/types/message_claim_morse_account.go index 911286226..cc486a9e0 100644 --- a/x/migration/types/message_claim_morse_account.go +++ b/x/migration/types/message_claim_morse_account.go @@ -27,6 +27,10 @@ func NewMsgClaimMorseAccount( } morseSignature, err := morsePrivateKey.Sign(msgBz) + if err != nil { + return nil, err + } + msg.MorseSignature = hex.EncodeToString(morseSignature) return msg, nil diff --git a/x/migration/types/message_claim_morse_account_test.go b/x/migration/types/message_claim_morse_account_test.go index 8f16b77f6..a16d52cbe 100644 --- a/x/migration/types/message_claim_morse_account_test.go +++ b/x/migration/types/message_claim_morse_account_test.go @@ -51,8 +51,3 @@ func TestMsgClaimMorseAccount_ValidateBasic(t *testing.T) { }) } } - -// TODO_IN_THIS_COMMIT: error cases... -// - empty signature -// - invalid length morse hex addr -// - invalid shannon bech32 addr From 952bf174b51f0518a8a0d530668e4615057b4324 Mon Sep 17 00:00:00 2001 From: Bryan White Date: Wed, 19 Feb 2025 13:04:29 +0100 Subject: [PATCH 10/18] refactor: extract keeper methods from msgServer handler --- x/migration/keeper/morse_claimable_account.go | 51 ++++++++++++++----- .../keeper/msg_server_claim_morse_account.go | 25 ++++----- x/migration/types/morse_claimable_account.go | 7 +++ 3 files changed, 54 insertions(+), 29 deletions(-) create mode 100644 x/migration/types/morse_claimable_account.go diff --git a/x/migration/keeper/morse_claimable_account.go b/x/migration/keeper/morse_claimable_account.go index dd3e3e43a..c47ee5b1f 100644 --- a/x/migration/keeper/morse_claimable_account.go +++ b/x/migration/keeper/morse_claimable_account.go @@ -6,16 +6,17 @@ import ( "cosmossdk.io/store/prefix" storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/runtime" + cosmostypes "github.com/cosmos/cosmos-sdk/types" - "github.com/pokt-network/poktroll/x/migration/types" + migrationtypes "github.com/pokt-network/poktroll/x/migration/types" ) // SetMorseClaimableAccount set a specific morseClaimableAccount in the store from its index -func (k Keeper) SetMorseClaimableAccount(ctx context.Context, morseClaimableAccount types.MorseClaimableAccount) { +func (k Keeper) SetMorseClaimableAccount(ctx context.Context, morseClaimableAccount migrationtypes.MorseClaimableAccount) { storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) - store := prefix.NewStore(storeAdapter, types.KeyPrefix(types.MorseClaimableAccountKeyPrefix)) + store := prefix.NewStore(storeAdapter, migrationtypes.KeyPrefix(migrationtypes.MorseClaimableAccountKeyPrefix)) morseClaimableAccountBz := k.cdc.MustMarshal(&morseClaimableAccount) - store.Set(types.MorseClaimableAccountKey( + store.Set(migrationtypes.MorseClaimableAccountKey( morseClaimableAccount.MorseSrcAddress, ), morseClaimableAccountBz) } @@ -25,11 +26,11 @@ func (k Keeper) GetMorseClaimableAccount( ctx context.Context, address string, -) (morseClaimableAccount types.MorseClaimableAccount, found bool) { +) (morseClaimableAccount migrationtypes.MorseClaimableAccount, found bool) { storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) - store := prefix.NewStore(storeAdapter, types.KeyPrefix(types.MorseClaimableAccountKeyPrefix)) + store := prefix.NewStore(storeAdapter, migrationtypes.KeyPrefix(migrationtypes.MorseClaimableAccountKeyPrefix)) - morseClaimableAccountBz := store.Get(types.MorseClaimableAccountKey( + morseClaimableAccountBz := store.Get(migrationtypes.MorseClaimableAccountKey( address, )) if morseClaimableAccountBz == nil { @@ -47,22 +48,22 @@ func (k Keeper) RemoveMorseClaimableAccount( ) { storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) - store := prefix.NewStore(storeAdapter, types.KeyPrefix(types.MorseClaimableAccountKeyPrefix)) - store.Delete(types.MorseClaimableAccountKey( + store := prefix.NewStore(storeAdapter, migrationtypes.KeyPrefix(migrationtypes.MorseClaimableAccountKeyPrefix)) + store.Delete(migrationtypes.MorseClaimableAccountKey( address, )) } // GetAllMorseClaimableAccounts returns all morseClaimableAccount -func (k Keeper) GetAllMorseClaimableAccounts(ctx context.Context) (list []types.MorseClaimableAccount) { +func (k Keeper) GetAllMorseClaimableAccounts(ctx context.Context) (list []migrationtypes.MorseClaimableAccount) { storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) - store := prefix.NewStore(storeAdapter, types.KeyPrefix(types.MorseClaimableAccountKeyPrefix)) + store := prefix.NewStore(storeAdapter, migrationtypes.KeyPrefix(migrationtypes.MorseClaimableAccountKeyPrefix)) iterator := storetypes.KVStorePrefixIterator(store, []byte{}) defer iterator.Close() for ; iterator.Valid(); iterator.Next() { - var morseClaimableAccount types.MorseClaimableAccount + var morseClaimableAccount migrationtypes.MorseClaimableAccount k.cdc.MustUnmarshal(iterator.Value(), &morseClaimableAccount) list = append(list, morseClaimableAccount) } @@ -75,7 +76,7 @@ func (k Keeper) GetAllMorseClaimableAccounts(ctx context.Context) (list []types. // DEV_NOTE: It assumes that the MorseAccountState has already been validated. func (k Keeper) ImportFromMorseAccountState( ctx context.Context, - morseAccountState *types.MorseAccountState, + morseAccountState *migrationtypes.MorseAccountState, ) { for _, morseAccount := range morseAccountState.Accounts { // DEV_NOTE: Ensure all MorseClaimableAccounts are initially unclaimed. @@ -83,3 +84,27 @@ func (k Keeper) ImportFromMorseAccountState( k.SetMorseClaimableAccount(ctx, *morseAccount) } } + +// MintClaimedMorseTokens mints the given coinToMint to the given destAddress. +func (k Keeper) MintClaimedMorseTokens( + ctx context.Context, + destAddress cosmostypes.AccAddress, + coinToMint cosmostypes.Coin, +) error { + // Mint the sum of the account balance (coinToMint) and any actor stakes to the migration module account. + if err := k.bankKeeper.MintCoins( + ctx, + migrationtypes.ModuleName, + cosmostypes.NewCoins(coinToMint), + ); err != nil { + return err + } + + // Transfer the coinToMint to the shannonDestAddress account. + return k.bankKeeper.SendCoinsFromModuleToAccount( + ctx, + migrationtypes.ModuleName, + destAddress, + cosmostypes.NewCoins(coinToMint), + ) +} diff --git a/x/migration/keeper/msg_server_claim_morse_account.go b/x/migration/keeper/msg_server_claim_morse_account.go index 0035ed266..1bf758e71 100644 --- a/x/migration/keeper/msg_server_claim_morse_account.go +++ b/x/migration/keeper/msg_server_claim_morse_account.go @@ -4,7 +4,7 @@ import ( "context" cosmostypes "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/errors" + cosmoserrors "github.com/cosmos/cosmos-sdk/types/errors" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -24,7 +24,7 @@ func (k msgServer) ClaimMorseAccount(ctx context.Context, msg *migrationtypes.Ms if err != nil { return nil, status.Error( codes.InvalidArgument, - errors.ErrInvalidAddress.Wrapf( + cosmoserrors.ErrInvalidAddress.Wrapf( "failed to parse shannon destination address (%s): %s", msg.ShannonDestAddress, err, ).Error(), @@ -47,8 +47,7 @@ func (k msgServer) ClaimMorseAccount(ctx context.Context, msg *migrationtypes.Ms } // Ensure that the given MorseClaimableAccount has not already been claimed. - if morseClaimableAccount.ClaimedAtHeight > 0 || - morseClaimableAccount.ShannonDestAddress != "" { + if morseClaimableAccount.IsClaimed() { return nil, status.Error( codes.FailedPrecondition, migrationtypes.ErrMorseAccountClaim.Wrapf( @@ -60,8 +59,11 @@ func (k msgServer) ClaimMorseAccount(ctx context.Context, msg *migrationtypes.Ms ) } - // Update the MorseClaimableAccount + // Set ShannonDestAddress & ClaimedAtHeight (claim). + morseClaimableAccount.ShannonDestAddress = shannonAccAddr.String() morseClaimableAccount.ClaimedAtHeight = sdkCtx.BlockHeight() + + // Update the MorseClaimableAccount. k.SetMorseClaimableAccount( sdkCtx, morseClaimableAccount, @@ -73,17 +75,8 @@ func (k msgServer) ClaimMorseAccount(ctx context.Context, msg *migrationtypes.Ms Add(morseClaimableAccount.ApplicationStake). Add(morseClaimableAccount.SupplierStake) - // Mint the sum of the account balance (totalTokens) and any actor stakes to the migration module account. - if err = k.bankKeeper.MintCoins(ctx, migrationtypes.ModuleName, cosmostypes.NewCoins(totalTokens)); err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } - - // Transfer the totalTokens to the shannonDestAddress account. - if err = k.bankKeeper.SendCoinsFromModuleToAccount(ctx, - migrationtypes.ModuleName, - shannonAccAddr, - cosmostypes.NewCoins(totalTokens), - ); err != nil { + // Mint the totalTokens to the shannonDestAddress account balance. + if err = k.MintClaimedMorseTokens(ctx, shannonAccAddr, totalTokens); err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/x/migration/types/morse_claimable_account.go b/x/migration/types/morse_claimable_account.go new file mode 100644 index 000000000..39fc1af01 --- /dev/null +++ b/x/migration/types/morse_claimable_account.go @@ -0,0 +1,7 @@ +package types + +// IsClaimed returns true if the MorseClaimableAccount has been claimed; +// i.e. ShannonDestAddress is not empty OR the ClaimedAtHeight is greater than 0. +func (m *MorseClaimableAccount) IsClaimed() bool { + return m.ShannonDestAddress != "" || m.ClaimedAtHeight > 0 +} From b49e9ad2da6d85536f05d3a48f1aa89890b608c4 Mon Sep 17 00:00:00 2001 From: Bryan White Date: Wed, 19 Feb 2025 13:04:47 +0100 Subject: [PATCH 11/18] test: refactor testutil --- .../morse_account_import_and_claim_test.go | 1 + testutil/keeper/migration.go | 77 +++++++++++++------ .../msg_server_claim_morse_acount_test.go | 1 + 3 files changed, 56 insertions(+), 23 deletions(-) diff --git a/tests/integration/migration/morse_account_import_and_claim_test.go b/tests/integration/migration/morse_account_import_and_claim_test.go index 64daf7630..77b4cbeb2 100644 --- a/tests/integration/migration/morse_account_import_and_claim_test.go +++ b/tests/integration/migration/morse_account_import_and_claim_test.go @@ -85,6 +85,7 @@ func TestMsgServer_CreateMorseAccountClaim(t *testing.T) { // Assert that the MorseClaimableAccount was updated on-chain. expectedMorseClaimableAccount := *accountState.Accounts[0] + expectedMorseClaimableAccount.ShannonDestAddress = shannonDestAddr expectedMorseClaimableAccount.ClaimedAtHeight = app.GetSdkCtx().BlockHeight() - 1 morseAccountQuerier := migrationtypes.NewQueryClient(app.QueryHelper()) diff --git a/testutil/keeper/migration.go b/testutil/keeper/migration.go index 363ac76e1..400bcedf3 100644 --- a/testutil/keeper/migration.go +++ b/testutil/keeper/migration.go @@ -21,11 +21,26 @@ import ( "github.com/pokt-network/poktroll/testutil/migration/mocks" "github.com/pokt-network/poktroll/x/migration/keeper" - "github.com/pokt-network/poktroll/x/migration/types" + migrationtypes "github.com/pokt-network/poktroll/x/migration/types" ) -func MigrationKeeper(t testing.TB) (keeper.Keeper, sdk.Context) { - storeKey := storetypes.NewKVStoreKey(types.StoreKey) +// MigrationKeeperConfig is a configuration struct for the MigrationKeeper testutil. +type MigrationKeeperConfig struct { + bankKeeper migrationtypes.BankKeeper +} + +// MigrationKeeperOptionFn is a function which receives and potentially modifies +// the MigrationKeeperConfig during construction of the MigrationKeeper testutil. +type MigrationKeeperOptionFn func(cfg *MigrationKeeperConfig) + +// MigrationKeeper returns a new migration module keeper with mocked dependencies +// (i.e. gateway, app, & supplier keepers). Mocked dependencies are configurable +// via the MigrationKeeperOptionFns. +func MigrationKeeper( + t testing.TB, + opts ...MigrationKeeperOptionFn, +) (keeper.Keeper, sdk.Context) { + storeKey := storetypes.NewKVStoreKey(migrationtypes.StoreKey) db := dbm.NewMemDB() stateStore := store.NewCommitMultiStore(db, log.NewNopLogger(), metrics.NewNoOpMetrics()) @@ -37,6 +52,40 @@ func MigrationKeeper(t testing.TB) (keeper.Keeper, sdk.Context) { authority := authtypes.NewModuleAddress(govtypes.ModuleName) ctrl := gomock.NewController(t) + mockAccountKeeper := mocks.NewMockAccountKeeper(ctrl) + + cfg := defaultConfigWithMocks(ctrl) + for _, opt := range opts { + opt(cfg) + } + + k := keeper.NewKeeper( + cdc, + runtime.NewKVStoreService(storeKey), + log.NewNopLogger(), + authority.String(), + mockAccountKeeper, + cfg.bankKeeper, + ) + + ctx := sdk.NewContext(stateStore, cmtproto.Header{}, false, log.NewNopLogger()) + + // Initialize params + if err := k.SetParams(ctx, migrationtypes.DefaultParams()); err != nil { + panic(err) + } + + return k, ctx +} + +// WithBankKeeper assigns the given BankKeeper to the MigrationKeeperConfig. +func WithBankKeeper(bankKeeper migrationtypes.BankKeeper) MigrationKeeperOptionFn { + return func(cfg *MigrationKeeperConfig) { + cfg.bankKeeper = bankKeeper + } +} + +func defaultConfigWithMocks(ctrl *gomock.Controller) *MigrationKeeperConfig { mockBankKeeper := mocks.NewMockBankKeeper(ctrl) mockBankKeeper.EXPECT(). SpendableCoins(gomock.Any(), gomock.Any()). @@ -50,32 +99,14 @@ func MigrationKeeper(t testing.TB) (keeper.Keeper, sdk.Context) { return sdk.Coins{} }, ).AnyTimes() - mockBankKeeper.EXPECT(). MintCoins(gomock.Any(), gomock.Any(), gomock.Any()). AnyTimes() - mockBankKeeper.EXPECT(). SendCoinsFromModuleToAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). AnyTimes() - mockAccountKeeper := mocks.NewMockAccountKeeper(ctrl) - - k := keeper.NewKeeper( - cdc, - runtime.NewKVStoreService(storeKey), - log.NewNopLogger(), - authority.String(), - mockAccountKeeper, - mockBankKeeper, - ) - - ctx := sdk.NewContext(stateStore, cmtproto.Header{}, false, log.NewNopLogger()) - - // Initialize params - if err := k.SetParams(ctx, types.DefaultParams()); err != nil { - panic(err) + return &MigrationKeeperConfig{ + bankKeeper: mockBankKeeper, } - - return k, ctx } diff --git a/x/migration/keeper/msg_server_claim_morse_acount_test.go b/x/migration/keeper/msg_server_claim_morse_acount_test.go index 736d12544..edb204823 100644 --- a/x/migration/keeper/msg_server_claim_morse_acount_test.go +++ b/x/migration/keeper/msg_server_claim_morse_acount_test.go @@ -68,6 +68,7 @@ func TestMsgServer_ClaimMorseAccount_Success(t *testing.T) { // Assert that the persisted MorseClaimableAccount is updated. expectedMorseAccount := morseAccount + expectedMorseAccount.ShannonDestAddress = msgClaim.GetShannonDestAddress() expectedMorseAccount.ClaimedAtHeight = ctx.BlockHeight() foundMorseAccount, found := k.GetMorseClaimableAccount(ctx, msgClaim.MorseSrcAddress) require.True(t, found) From 3411b2978c63c30db847eef37490b81ac8dabe5d Mon Sep 17 00:00:00 2001 From: Bryan White Date: Wed, 19 Feb 2025 14:54:20 +0100 Subject: [PATCH 12/18] refactor: base integration suite bank client --- .../application/application_transfer_test.go | 48 ++++++++----------- testutil/integration/suites/application.go | 4 +- testutil/integration/suites/base.go | 13 ++++- testutil/integration/suites/base_test.go | 16 ++----- testutil/integration/suites/interface.go | 4 +- 5 files changed, 40 insertions(+), 45 deletions(-) diff --git a/tests/integration/application/application_transfer_test.go b/tests/integration/application/application_transfer_test.go index ad0b49cd7..5eebc0056 100644 --- a/tests/integration/application/application_transfer_test.go +++ b/tests/integration/application/application_transfer_test.go @@ -4,7 +4,6 @@ import ( "testing" cosmostypes "github.com/cosmos/cosmos-sdk/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" @@ -81,7 +80,7 @@ func (s *appTransferTestSuite) SetupTest() { }) // Assert the onchain state shows the application 3 as NOT staked. - _, queryErr := s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app3) + _, queryErr := s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app3) require.ErrorContains(s.T(), queryErr, "application not found") require.ErrorContains(s.T(), queryErr, s.app3) } @@ -110,7 +109,7 @@ func (s *appTransferTestSuite) TestSingleSourceToNonexistentDestinationSucceeds( require.EqualValues(s.T(), expectedPendingTransfer, pendingTransfer) // Query and assert application pending transfer field updated in the store. - foundApp1, err := s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app1) + foundApp1, err := s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app1) require.NoError(s.T(), err) require.EqualValues(s.T(), expectedPendingTransfer, foundApp1.GetPendingTransfer()) @@ -129,7 +128,7 @@ func (s *appTransferTestSuite) TestSingleSourceToNonexistentDestinationSucceeds( s.GetApp().NextBlocks(s.T(), int(blocksUntilTransferEndHeight)-1) // Assert that app1 is in transfer period. - foundApp1, err = s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app1) + foundApp1, err = s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app1) require.NoError(s.T(), err) require.Equal(s.T(), s.app1, foundApp1.GetAddress()) @@ -139,7 +138,7 @@ func (s *appTransferTestSuite) TestSingleSourceToNonexistentDestinationSucceeds( s.GetApp().NextBlock(s.T()) // Query for and assert that the destination application was created. - foundApp3, err := s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app3) + foundApp3, err := s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app3) require.NoError(s.T(), err) // Assert that the destination application was created with the correct state. @@ -164,21 +163,18 @@ func (s *appTransferTestSuite) TestSingleSourceToNonexistentDestinationSucceeds( s.shouldObserveTransferEndEvent(&foundApp3, s.app1) // Assert that app1 is unstaked. - _, err = s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app1) + _, err = s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app1) require.ErrorContains(s.T(), err, "application not found") require.ErrorContains(s.T(), err, s.app1) // Assert that app1's bank balance has not changed. - balanceRes, err := s.GetBankQueryClient().Balance(s.SdkCtx(), &banktypes.QueryBalanceRequest{ - Address: s.app1, - Denom: volatile.DenomuPOKT, - }) + balance, err := s.GetBankQueryClient(s.T()).GetBalance(s.SdkCtx(), s.app1) require.NoError(s.T(), err) - require.NotNil(s.T(), balanceRes) + require.NotNil(s.T(), balance) require.EqualValues(s.T(), cosmostypes.NewInt64Coin(volatile.DenomuPOKT, appFundAmount-stakeAmount), - *balanceRes.GetBalance(), + *balance, ) } @@ -228,7 +224,7 @@ func (s *appTransferTestSuite) TestMultipleSourceToSameNonexistentDestinationMer require.EqualValues(s.T(), expectedPendingTransfer, pendingTransfer) // Query and assert application pending transfer field updated in the store. - foundSrcApp, srcAppErr := s.GetAppQueryClient().GetApplication(s.SdkCtx(), expectedSrcBech32) + foundSrcApp, srcAppErr := s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), expectedSrcBech32) require.NoError(s.T(), srcAppErr) require.EqualValues(s.T(), expectedPendingTransfer, foundSrcApp.GetPendingTransfer()) @@ -257,7 +253,7 @@ func (s *appTransferTestSuite) TestMultipleSourceToSameNonexistentDestinationMer s.GetApp().NextBlocks(s.T(), int(blocksUntilTransferEndHeight)-1) // Assert that app1 is in transfer period. - foundApp1, err := s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app1) + foundApp1, err := s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app1) require.NoError(s.T(), err) require.Equal(s.T(), s.app1, foundApp1.GetAddress()) @@ -267,7 +263,7 @@ func (s *appTransferTestSuite) TestMultipleSourceToSameNonexistentDestinationMer s.GetApp().NextBlock(s.T()) // Assert that app3 is staked with the sum amount: app1 + app2. - foundApp3, err := s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app3) + foundApp3, err := s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app3) require.NoError(s.T(), err) require.Equal(s.T(), s.app3, foundApp3.GetAddress()) @@ -308,30 +304,26 @@ func (s *appTransferTestSuite) TestMultipleSourceToSameNonexistentDestinationMer require.Equal(s.T(), len(expectedApp3ServiceIds), len(foundApp3.GetServiceConfigs())) // Assert that app1 is unstaked. - foundApp1, err = s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app1) + foundApp1, err = s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app1) require.ErrorContains(s.T(), err, "application not found") require.ErrorContains(s.T(), err, s.app1) // Assert that app2 is unstaked. - _, err = s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app2) + _, err = s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app2) require.ErrorContains(s.T(), err, "application not found") require.ErrorContains(s.T(), err, s.app2) // Assert that app1's bank balance has not changed - balRes, err := s.GetBankQueryClient().Balance(s.SdkCtx(), &banktypes.QueryBalanceRequest{ - Address: s.app1, - Denom: volatile.DenomuPOKT, - }) require.NoError(s.T(), err) - require.Equal(s.T(), appFundAmount-stakeAmount, balRes.GetBalance().Amount.Int64()) + + balance, err := s.GetBankQueryClient(s.T()).GetBalance(s.SdkCtx(), s.app1) + require.NoError(s.T(), err) + require.Equal(s.T(), appFundAmount-stakeAmount, balance.Amount.Int64()) // Assert that app2's bank balance has not changed - balRes, err = s.GetBankQueryClient().Balance(s.SdkCtx(), &banktypes.QueryBalanceRequest{ - Address: s.app2, - Denom: volatile.DenomuPOKT, - }) + balance, err = s.GetBankQueryClient(s.T()).GetBalance(s.SdkCtx(), s.app2) require.NoError(s.T(), err) - require.Equal(s.T(), appFundAmount-stakeAmount, balRes.GetBalance().Amount.Int64()) + require.Equal(s.T(), appFundAmount-stakeAmount, balance.Amount.Int64()) } // TODO_TEST: @@ -391,7 +383,7 @@ func (s *appTransferTestSuite) setupStakeApps(appBech32ToServiceIdsMap map[strin require.Equal(s.T(), stakeAmount, stakeAppRes.GetApplication().GetStake().Amount.Int64()) // Assert the onchain state shows the application as staked. - foundApp, queryErr := s.GetAppQueryClient().GetApplication(s.SdkCtx(), appBech32) + foundApp, queryErr := s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), appBech32) require.NoError(s.T(), queryErr) require.Equal(s.T(), appBech32, foundApp.GetAddress()) require.Equal(s.T(), stakeAmount, foundApp.GetStake().Amount.Int64()) diff --git a/testutil/integration/suites/application.go b/testutil/integration/suites/application.go index 86b22fccf..a54b2a756 100644 --- a/testutil/integration/suites/application.go +++ b/testutil/integration/suites/application.go @@ -24,10 +24,10 @@ type ApplicationModuleSuite struct { // GetAppQueryClient constructs and returns a query client for the application // module of the integration app. -func (s *ApplicationModuleSuite) GetAppQueryClient() client.ApplicationQueryClient { +func (s *ApplicationModuleSuite) GetAppQueryClient(t *testing.T) client.ApplicationQueryClient { deps := depinject.Supply(s.GetApp().QueryHelper()) appQueryClient, err := query.NewApplicationQuerier(deps) - require.NoError(s.T(), err) + require.NoError(t, err) return appQueryClient } diff --git a/testutil/integration/suites/base.go b/testutil/integration/suites/base.go index 491cae620..1a2adb5f6 100644 --- a/testutil/integration/suites/base.go +++ b/testutil/integration/suites/base.go @@ -6,6 +6,7 @@ import ( "testing" "cosmossdk.io/core/appmodule" + "cosmossdk.io/depinject" "github.com/cosmos/cosmos-sdk/codec" cosmostypes "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" @@ -14,6 +15,8 @@ import ( "github.com/stretchr/testify/suite" "github.com/pokt-network/poktroll/app/volatile" + "github.com/pokt-network/poktroll/pkg/client" + "github.com/pokt-network/poktroll/pkg/client/query" "github.com/pokt-network/poktroll/pkg/polylog" _ "github.com/pokt-network/poktroll/pkg/polylog/polyzero" "github.com/pokt-network/poktroll/testutil/integration" @@ -97,8 +100,14 @@ func (s *BaseIntegrationSuite) FundAddress( // GetBankQueryClient constructs and returns a query client for the bank module // of the integration app. -func (s *BaseIntegrationSuite) GetBankQueryClient() banktypes.QueryClient { - return banktypes.NewQueryClient(s.GetApp().QueryHelper()) +func (s *BaseIntegrationSuite) GetBankQueryClient(t *testing.T) client.BankQueryClient { + t.Helper() + + deps := depinject.Supply(s.GetApp().QueryHelper()) + bankqueryClient, err := query.NewBankQuerier(deps) + require.NoError(t, err) + + return bankqueryClient } // FilterEvents returns the events from the event manager which match the given diff --git a/testutil/integration/suites/base_test.go b/testutil/integration/suites/base_test.go index 6952668ba..a4694797f 100644 --- a/testutil/integration/suites/base_test.go +++ b/testutil/integration/suites/base_test.go @@ -93,24 +93,18 @@ func (s *baseIntegrationSuiteTestSuite) TestFundAddressAndGetBankQueryClient() { require.NoError(s.T(), err) // Assert that the balance is zero before funding. - bankQueryClient := s.GetBankQueryClient() - balRes, err := bankQueryClient.Balance(s.SdkCtx(), &banktypes.QueryBalanceRequest{ - Address: fundAddr.String(), - Denom: volatile.DenomuPOKT, - }) + bankClient := s.GetBankQueryClient(s.T()) + balance, err := bankClient.GetBalance(s.SdkCtx(), fundAddr.String()) require.NoError(s.T(), err) - require.Equal(s.T(), int64(0), balRes.GetBalance().Amount.Int64()) + require.Equal(s.T(), int64(0), balance.Amount.Int64()) // Fund the address. s.FundAddress(s.T(), fundAddr, fundAmount) // Assert that the balance amount is equal to fundAmount. - balRes, err = bankQueryClient.Balance(s.SdkCtx(), &banktypes.QueryBalanceRequest{ - Address: fundAddr.String(), - Denom: volatile.DenomuPOKT, - }) + balance, err = bankClient.GetBalance(s.SdkCtx(), fundAddr.String()) require.NoError(s.T(), err) - require.Equal(s.T(), fundAmount, balRes.GetBalance().Amount.Int64()) + require.Equal(s.T(), fundAmount, balance.Amount.Int64()) } func (s *baseIntegrationSuiteTestSuite) TestFilterLatestEventsWithNewMsgEventMatchFn() { diff --git a/testutil/integration/suites/interface.go b/testutil/integration/suites/interface.go index d88246a90..0d4321d8f 100644 --- a/testutil/integration/suites/interface.go +++ b/testutil/integration/suites/interface.go @@ -4,8 +4,8 @@ import ( "testing" cosmostypes "github.com/cosmos/cosmos-sdk/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/pokt-network/poktroll/pkg/client" "github.com/pokt-network/poktroll/testutil/integration" ) @@ -31,7 +31,7 @@ type IntegrationSuite interface { FundAddress(t *testing.T, addr cosmostypes.AccAddress, amtUpokt int64) // GetBankQueryClient constructs and returns a query client for the bank module // of the integration app. - GetBankQueryClient() banktypes.QueryClient + GetBankQueryClient(t *testing.T) client.BankQueryClient // FilterEvents returns the events from the event manager which match the given // matchFn. Events are returned in reverse order, i.e. the most recent event is From 7128b8398983d98cdb205ea22bc238bbc3a4db8a Mon Sep 17 00:00:00 2001 From: Bryan White Date: Wed, 19 Feb 2025 14:54:44 +0100 Subject: [PATCH 13/18] test: refactor integration test to a suite --- .../morse_account_import_and_claim_test.go | 123 ++++++++---------- testutil/integration/suites/migration.go | 104 +++++++++++++++ 2 files changed, 159 insertions(+), 68 deletions(-) create mode 100644 testutil/integration/suites/migration.go diff --git a/tests/integration/migration/morse_account_import_and_claim_test.go b/tests/integration/migration/morse_account_import_and_claim_test.go index 77b4cbeb2..627617744 100644 --- a/tests/integration/migration/morse_account_import_and_claim_test.go +++ b/tests/integration/migration/morse_account_import_and_claim_test.go @@ -3,106 +3,93 @@ package migration import ( "testing" - "cosmossdk.io/depinject" "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" "github.com/pokt-network/poktroll/app/volatile" - "github.com/pokt-network/poktroll/pkg/client/query" - "github.com/pokt-network/poktroll/testutil/integration" + "github.com/pokt-network/poktroll/testutil/integration/suites" "github.com/pokt-network/poktroll/testutil/sample" - "github.com/pokt-network/poktroll/testutil/testmigration" migrationtypes "github.com/pokt-network/poktroll/x/migration/types" ) -func TestMsgServer_CreateMorseAccountClaim(t *testing.T) { - app := integration.NewCompleteIntegrationApp(t) +type MigrationModuleTestSuite struct { + suites.MigrationModuleSuite - // Generate Morse claimable accounts. - numAccounts := 10 - _, accountState := testmigration.NewMorseStateExportAndAccountState(t, numAccounts) + // TODO_IN_THIS_COMMIT: godoc... + numAccounts int +} + +func (s *MigrationModuleTestSuite) SetupTest() { + // Initialize a new integration app for the suite. + s.NewApp(s.T()) - msgImport, err := migrationtypes.NewMsgImportMorseClaimableAccounts( - authtypes.NewModuleAddress(govtypes.ModuleName).String(), - *accountState, - ) - require.NoError(t, err) + s.numAccounts = 10 - // Import Morse claimable accounts. - resAny, err := app.RunMsg(t, msgImport) - require.NoError(t, err) + // Assign the app to nested suites. + s.AppSuite.SetApp(s.GetApp()) +} - msgImportRes, ok := resAny.(*migrationtypes.MsgImportMorseClaimableAccountsResponse) - require.True(t, ok) +func TestMigrationModuleSuite(t *testing.T) { + suite.Run(t, &MigrationModuleTestSuite{}) +} - morseAccountStateHash, err := accountState.GetHash() - require.NoError(t, err) +// TODO_IN_THIS_COMMIT: godoc... +func (s *MigrationModuleTestSuite) TestImportMorseClaimableAccounts() { + s.GenerateMorseAccountState(s.T(), s.numAccounts) + msgImportRes := s.ImportMorseClaimableAccounts(s.T()) + morseAccountStateHash, err := s.GetAccountState(s.T()).GetHash() + require.NoError(s.T(), err) expectedMsgImportRes := &migrationtypes.MsgImportMorseClaimableAccountsResponse{ StateHash: morseAccountStateHash, - NumAccounts: uint64(numAccounts), + NumAccounts: uint64(s.numAccounts), } - require.Equal(t, expectedMsgImportRes, msgImportRes) + require.Equal(s.T(), expectedMsgImportRes, msgImportRes) +} - deps := depinject.Supply(app.QueryHelper()) - bankClient, err := query.NewBankQuerier(deps) - require.NoError(t, err) +// TODO_IN_THIS_COMMIT: godoc... +func (s *MigrationModuleTestSuite) TestClaimMorseAccount() { + s.GenerateMorseAccountState(s.T(), s.numAccounts) + s.ImportMorseClaimableAccounts(s.T()) - // Assert that the shannonDestAddr account initially has a zero balance. shannonDestAddr := sample.AccAddress() - shannonDestBalance, err := bankClient.GetBalance(app.GetSdkCtx(), shannonDestAddr) - require.NoError(t, err) - require.Equal(t, int64(0), shannonDestBalance.Amount.Int64()) - - morsePrivateKey := testmigration.NewMorsePrivateKey(t, 1) - morseSrcAddr := morsePrivateKey.PubKey().Address().String() - require.Equal(t, morseSrcAddr, accountState.Accounts[0].MorseSrcAddress) - - morseClaimMsg, err := migrationtypes.NewMsgClaimMorseAccount( - shannonDestAddr, - morseSrcAddr, - morsePrivateKey, - ) - require.NoError(t, err) - - // Claim a Morse claimable account. - resAny, err = app.RunMsg(t, morseClaimMsg) - require.NoError(t, err) - - expectedBalance := sdk.NewInt64Coin(volatile.DenomuPOKT, 1110111) + + bankClient := s.GetBankQueryClient(s.T()) + shannonDestBalance, err := bankClient.GetBalance(s.SdkCtx(), shannonDestAddr) + require.NoError(s.T(), err) + require.Equal(s.T(), int64(0), shannonDestBalance.Amount.Int64()) + + morseSrcAddr, claimAccountRes := s.ClaimMorseAccount(s.T(), 1, shannonDestAddr) + + expectedMorseClaimableAccount := s.GetAccountState(s.T()).Accounts[0] + expectedBalance := expectedMorseClaimableAccount.GetUnstakedBalance(). + Add(expectedMorseClaimableAccount.GetApplicationStake()). + Add(expectedMorseClaimableAccount.GetSupplierStake()) + expectedClaimAccountRes := &migrationtypes.MsgClaimMorseAccountResponse{ MorseSrcAddress: morseSrcAddr, ClaimedBalance: expectedBalance, - ClaimedAtHeight: app.GetSdkCtx().BlockHeight() - 1, + ClaimedAtHeight: s.SdkCtx().BlockHeight() - 1, } - - claimAccountRes, ok := resAny.(*migrationtypes.MsgClaimMorseAccountResponse) - require.True(t, ok) - require.Equal(t, expectedClaimAccountRes, claimAccountRes) + require.Equal(s.T(), expectedClaimAccountRes, claimAccountRes) // Assert that the MorseClaimableAccount was updated on-chain. - expectedMorseClaimableAccount := *accountState.Accounts[0] expectedMorseClaimableAccount.ShannonDestAddress = shannonDestAddr - expectedMorseClaimableAccount.ClaimedAtHeight = app.GetSdkCtx().BlockHeight() - 1 - - morseAccountQuerier := migrationtypes.NewQueryClient(app.QueryHelper()) - morseClaimableAcctRes, err := morseAccountQuerier.MorseClaimableAccount(app.GetSdkCtx(), &migrationtypes.QueryGetMorseClaimableAccountRequest{ - Address: morseSrcAddr, - }) - require.NoError(t, err) - require.Equal(t, expectedMorseClaimableAccount, morseClaimableAcctRes.MorseClaimableAccount) + expectedMorseClaimableAccount.ClaimedAtHeight = s.SdkCtx().BlockHeight() - 1 + morseClaimableAccount := s.QueryMorseClaimableAccount(s.T(), morseSrcAddr) + require.Equal(s.T(), expectedMorseClaimableAccount, morseClaimableAccount) // Assert that the shannonDestAddr account balance has been updated. - shannonDestBalance, err = bankClient.GetBalance(app.GetSdkCtx(), shannonDestAddr) - require.NoError(t, err) - require.Equal(t, expectedBalance, *shannonDestBalance) + shannonDestBalance, err = bankClient.GetBalance(s.GetApp().GetSdkCtx(), shannonDestAddr) + require.NoError(s.T(), err) + require.Equal(s.T(), expectedBalance, *shannonDestBalance) // Assert that the migration module account balance returns to zero. migrationModuleAddress := authtypes.NewModuleAddress(migrationtypes.ModuleName).String() - migrationModuleBalance, err := bankClient.GetBalance(app.GetSdkCtx(), migrationModuleAddress) - require.NoError(t, err) - require.Equal(t, sdk.NewCoin(volatile.DenomuPOKT, math.ZeroInt()), *migrationModuleBalance) + migrationModuleBalance, err := bankClient.GetBalance(s.SdkCtx(), migrationModuleAddress) + require.NoError(s.T(), err) + require.Equal(s.T(), sdk.NewCoin(volatile.DenomuPOKT, math.ZeroInt()), *migrationModuleBalance) } diff --git a/testutil/integration/suites/migration.go b/testutil/integration/suites/migration.go new file mode 100644 index 000000000..0e8a78e33 --- /dev/null +++ b/testutil/integration/suites/migration.go @@ -0,0 +1,104 @@ +package suites + +import ( + "testing" + + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/stretchr/testify/require" + + "github.com/pokt-network/poktroll/testutil/testmigration" + migrationtypes "github.com/pokt-network/poktroll/x/migration/types" +) + +var _ IntegrationSuite = (*MigrationModuleSuite)(nil) + +// TODO_IN_THIS_COMMIT: godoc... +type MigrationModuleSuite struct { + BaseIntegrationSuite + // TODO_IN_THIS_COMMIT: godoc... set in #GenerateMorseAccountState(), used in #ImportMorseClaimableAccounts(). + accountState *migrationtypes.MorseAccountState + // TODO_IN_THIS_COMMIT: godoc... set in #GenerateMorseAccountState(), used in #ImportMorseClaimableAccounts(). + numAccounts int + + // TODO_UPNEXT(@bryanchriswhite, #1043): Add ApplicationModuleSuite to the suite. + // AppSuite ApplicationModuleSuite +} + +// TODO_IN_THIS_COMMIT: godoc... +func (s *MigrationModuleSuite) GenerateMorseAccountState(t *testing.T, numAccounts int) { + s.numAccounts = numAccounts + _, s.accountState = testmigration.NewMorseStateExportAndAccountState(t, s.numAccounts) +} + +// TODO_IN_THIS_COMMIT: godoc... +func (s *MigrationModuleSuite) GetAccountState(t *testing.T) *migrationtypes.MorseAccountState { + require.NotNil(t, s.accountState) + return s.accountState +} + +// TODO_IN_THIS_COMMIT: godoc... +func (s *MigrationModuleSuite) ImportMorseClaimableAccounts(t *testing.T) *migrationtypes.MsgImportMorseClaimableAccountsResponse { + msgImport, err := migrationtypes.NewMsgImportMorseClaimableAccounts( + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + *s.accountState, + ) + require.NoError(t, err) + + // Import Morse claimable accounts. + resAny, err := s.GetApp().RunMsg(t, msgImport) + require.NoError(t, err) + + msgImportRes, ok := resAny.(*migrationtypes.MsgImportMorseClaimableAccountsResponse) + require.True(t, ok) + + return msgImportRes +} + +// TODO_IN_THIS_COMMIT: godoc... NOTE: morseAccountIdx is 1-based... +func (s *MigrationModuleSuite) ClaimMorseAccount( + t *testing.T, + morseAccountIdx uint64, + shannonDestAddr string, +) (morseSrcAddr string, _ *migrationtypes.MsgClaimMorseAccountResponse) { + t.Helper() + + morsePrivateKey := testmigration.NewMorsePrivateKey(t, morseAccountIdx) + morseSrcAddr = morsePrivateKey.PubKey().Address().String() + require.Equal(t, morseSrcAddr, s.accountState.Accounts[0].MorseSrcAddress) + + morseClaimMsg, err := migrationtypes.NewMsgClaimMorseAccount( + shannonDestAddr, + morseSrcAddr, + morsePrivateKey, + ) + require.NoError(t, err) + + // Claim a Morse claimable account. + resAny, err := s.GetApp().RunMsg(t, morseClaimMsg) + require.NoError(t, err) + + claimAccountRes, ok := resAny.(*migrationtypes.MsgClaimMorseAccountResponse) + require.True(t, ok) + + return morseSrcAddr, claimAccountRes +} + +// TODO_IN_THIS_COMMIT: godoc... +func (s *MigrationModuleSuite) QueryMorseClaimableAccount( + t *testing.T, + morseSrcAddr string, +) *migrationtypes.MorseClaimableAccount { + t.Helper() + + morseAccountQuerier := migrationtypes.NewQueryClient(s.GetApp().QueryHelper()) + morseClaimableAcctRes, err := morseAccountQuerier.MorseClaimableAccount( + s.SdkCtx(), + &migrationtypes.QueryMorseClaimableAccountRequest{ + Address: morseSrcAddr, + }, + ) + require.NoError(t, err) + + return &morseClaimableAcctRes.MorseClaimableAccount +} From c4fed01a1e86efc4adb06da20d86bca07da11626 Mon Sep 17 00:00:00 2001 From: Bryan White Date: Wed, 19 Feb 2025 15:10:04 +0100 Subject: [PATCH 14/18] chore: self-review improvements --- .../application/application_transfer_test.go | 2 - .../morse_account_import_and_claim_test.go | 23 ++++++---- testutil/integration/suites/migration.go | 43 +++++++++++-------- 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/tests/integration/application/application_transfer_test.go b/tests/integration/application/application_transfer_test.go index 5eebc0056..493993ae8 100644 --- a/tests/integration/application/application_transfer_test.go +++ b/tests/integration/application/application_transfer_test.go @@ -314,8 +314,6 @@ func (s *appTransferTestSuite) TestMultipleSourceToSameNonexistentDestinationMer require.ErrorContains(s.T(), err, s.app2) // Assert that app1's bank balance has not changed - require.NoError(s.T(), err) - balance, err := s.GetBankQueryClient(s.T()).GetBalance(s.SdkCtx(), s.app1) require.NoError(s.T(), err) require.Equal(s.T(), appFundAmount-stakeAmount, balance.Amount.Int64()) diff --git a/tests/integration/migration/morse_account_import_and_claim_test.go b/tests/integration/migration/morse_account_import_and_claim_test.go index 627617744..d10578d9c 100644 --- a/tests/integration/migration/morse_account_import_and_claim_test.go +++ b/tests/integration/migration/morse_account_import_and_claim_test.go @@ -18,41 +18,46 @@ import ( type MigrationModuleTestSuite struct { suites.MigrationModuleSuite - // TODO_IN_THIS_COMMIT: godoc... - numAccounts int + // numMorseClaimableAccounts is the number of morse claimable accounts to + // generate when calling #GenerateMorseAccountState. + numMorseClaimableAccounts int } func (s *MigrationModuleTestSuite) SetupTest() { // Initialize a new integration app for the suite. s.NewApp(s.T()) - s.numAccounts = 10 + s.numMorseClaimableAccounts = 10 // Assign the app to nested suites. - s.AppSuite.SetApp(s.GetApp()) + // TODO_UPNEXT(@bryanchriswhite, #1043): Initialize the app module suite. + // s.AppSuite.SetApp(s.GetApp()) } func TestMigrationModuleSuite(t *testing.T) { suite.Run(t, &MigrationModuleTestSuite{}) } -// TODO_IN_THIS_COMMIT: godoc... +// TestImportMorseClaimableAccounts tests claiming of morse claimable accounts. +// It only claims account balances and does not test staking any actors as a result of claiming. func (s *MigrationModuleTestSuite) TestImportMorseClaimableAccounts() { - s.GenerateMorseAccountState(s.T(), s.numAccounts) + s.GenerateMorseAccountState(s.T(), s.numMorseClaimableAccounts) msgImportRes := s.ImportMorseClaimableAccounts(s.T()) morseAccountStateHash, err := s.GetAccountState(s.T()).GetHash() require.NoError(s.T(), err) expectedMsgImportRes := &migrationtypes.MsgImportMorseClaimableAccountsResponse{ StateHash: morseAccountStateHash, - NumAccounts: uint64(s.numAccounts), + NumAccounts: uint64(s.numMorseClaimableAccounts), } require.Equal(s.T(), expectedMsgImportRes, msgImportRes) } -// TODO_IN_THIS_COMMIT: godoc... +// TestClaimMorseAccount tests claiming of a MorseClaimableAccounts. +// It only exercises claiming of account balances and does not exercise +// the staking any actors as a result of claiming. func (s *MigrationModuleTestSuite) TestClaimMorseAccount() { - s.GenerateMorseAccountState(s.T(), s.numAccounts) + s.GenerateMorseAccountState(s.T(), s.numMorseClaimableAccounts) s.ImportMorseClaimableAccounts(s.T()) shannonDestAddr := sample.AccAddress() diff --git a/testutil/integration/suites/migration.go b/testutil/integration/suites/migration.go index 0e8a78e33..5b8bff766 100644 --- a/testutil/integration/suites/migration.go +++ b/testutil/integration/suites/migration.go @@ -13,31 +13,34 @@ import ( var _ IntegrationSuite = (*MigrationModuleSuite)(nil) -// TODO_IN_THIS_COMMIT: godoc... +// MigrationModuleSuite is a test suite which abstracts common migration module +// functionality. It is intended to be embedded in dependent integration test suites. type MigrationModuleSuite struct { BaseIntegrationSuite - // TODO_IN_THIS_COMMIT: godoc... set in #GenerateMorseAccountState(), used in #ImportMorseClaimableAccounts(). - accountState *migrationtypes.MorseAccountState - // TODO_IN_THIS_COMMIT: godoc... set in #GenerateMorseAccountState(), used in #ImportMorseClaimableAccounts(). - numAccounts int - // TODO_UPNEXT(@bryanchriswhite, #1043): Add ApplicationModuleSuite to the suite. // AppSuite ApplicationModuleSuite + + // accountState is the generated MorseAccountState to be imported into the migration module. + accountState *migrationtypes.MorseAccountState + // numMorseClaimableAccounts is the number of morse claimable accounts to generate when calling #GenerateMorseAccountState. + numMorseClaimableAccounts int } -// TODO_IN_THIS_COMMIT: godoc... +// GenerateMorseAccountState generates a MorseAccountState with the given number of MorseClaimableAccounts. +// It updates the suite's #numMorseClaimableAccounts and #accountState fields. func (s *MigrationModuleSuite) GenerateMorseAccountState(t *testing.T, numAccounts int) { - s.numAccounts = numAccounts - _, s.accountState = testmigration.NewMorseStateExportAndAccountState(t, s.numAccounts) + s.numMorseClaimableAccounts = numAccounts + _, s.accountState = testmigration.NewMorseStateExportAndAccountState(t, s.numMorseClaimableAccounts) } -// TODO_IN_THIS_COMMIT: godoc... +// GetAccountState returns the suite's #accountState field. func (s *MigrationModuleSuite) GetAccountState(t *testing.T) *migrationtypes.MorseAccountState { require.NotNil(t, s.accountState) return s.accountState } -// TODO_IN_THIS_COMMIT: godoc... +// ImportMorseClaimableAccounts imports the MorseClaimableAccounts from the suite's +// #accountState field by running a MsgImportMorseClaimableAccounts message. func (s *MigrationModuleSuite) ImportMorseClaimableAccounts(t *testing.T) *migrationtypes.MsgImportMorseClaimableAccountsResponse { msgImport, err := migrationtypes.NewMsgImportMorseClaimableAccounts( authtypes.NewModuleAddress(govtypes.ModuleName).String(), @@ -55,21 +58,23 @@ func (s *MigrationModuleSuite) ImportMorseClaimableAccounts(t *testing.T) *migra return msgImportRes } -// TODO_IN_THIS_COMMIT: godoc... NOTE: morseAccountIdx is 1-based... +// ClaimMorseAccount claims the given MorseClaimableAccount by running a MsgClaimMorseAccount message. +// It returns the expected Morse source address and the MsgClaimMorseAccountResponse. +// DEV_NOTE: morseAccountIdx is 1-based. func (s *MigrationModuleSuite) ClaimMorseAccount( t *testing.T, morseAccountIdx uint64, shannonDestAddr string, -) (morseSrcAddr string, _ *migrationtypes.MsgClaimMorseAccountResponse) { +) (expectedMorseSrcAddr string, _ *migrationtypes.MsgClaimMorseAccountResponse) { t.Helper() morsePrivateKey := testmigration.NewMorsePrivateKey(t, morseAccountIdx) - morseSrcAddr = morsePrivateKey.PubKey().Address().String() - require.Equal(t, morseSrcAddr, s.accountState.Accounts[0].MorseSrcAddress) + expectedMorseSrcAddr = morsePrivateKey.PubKey().Address().String() + require.Equal(t, expectedMorseSrcAddr, s.accountState.Accounts[0].MorseSrcAddress) morseClaimMsg, err := migrationtypes.NewMsgClaimMorseAccount( shannonDestAddr, - morseSrcAddr, + expectedMorseSrcAddr, morsePrivateKey, ) require.NoError(t, err) @@ -81,10 +86,10 @@ func (s *MigrationModuleSuite) ClaimMorseAccount( claimAccountRes, ok := resAny.(*migrationtypes.MsgClaimMorseAccountResponse) require.True(t, ok) - return morseSrcAddr, claimAccountRes + return expectedMorseSrcAddr, claimAccountRes } -// TODO_IN_THIS_COMMIT: godoc... +// QueryMorseClaimableAccount queries the migration module for the given morseSrcAddr. func (s *MigrationModuleSuite) QueryMorseClaimableAccount( t *testing.T, morseSrcAddr string, @@ -94,7 +99,7 @@ func (s *MigrationModuleSuite) QueryMorseClaimableAccount( morseAccountQuerier := migrationtypes.NewQueryClient(s.GetApp().QueryHelper()) morseClaimableAcctRes, err := morseAccountQuerier.MorseClaimableAccount( s.SdkCtx(), - &migrationtypes.QueryMorseClaimableAccountRequest{ + &migrationtypes.QueryGetMorseClaimableAccountRequest{ Address: morseSrcAddr, }, ) From c4b037522daf4b4bd906e3c8da3b2b90e85b15ff Mon Sep 17 00:00:00 2001 From: Bryan White Date: Thu, 20 Feb 2025 14:39:55 +0100 Subject: [PATCH 15/18] chore: review feedback improvements Co-authored-by: red-0ne --- .../morse_account_import_and_claim_test.go | 2 +- .../keeper/msg_server_claim_morse_account.go | 27 ++++----- .../msg_server_claim_morse_acount_test.go | 5 +- .../types/message_claim_morse_account.go | 55 +++++++++++++++++-- .../types/message_claim_morse_account_test.go | 55 +++++++++++++++---- 5 files changed, 111 insertions(+), 33 deletions(-) diff --git a/tests/integration/migration/morse_account_import_and_claim_test.go b/tests/integration/migration/morse_account_import_and_claim_test.go index d10578d9c..a62a90292 100644 --- a/tests/integration/migration/morse_account_import_and_claim_test.go +++ b/tests/integration/migration/morse_account_import_and_claim_test.go @@ -65,7 +65,7 @@ func (s *MigrationModuleTestSuite) TestClaimMorseAccount() { bankClient := s.GetBankQueryClient(s.T()) shannonDestBalance, err := bankClient.GetBalance(s.SdkCtx(), shannonDestAddr) require.NoError(s.T(), err) - require.Equal(s.T(), int64(0), shannonDestBalance.Amount.Int64()) + require.True(s.T(), shannonDestBalance.IsZero()) morseSrcAddr, claimAccountRes := s.ClaimMorseAccount(s.T(), 1, shannonDestAddr) diff --git a/x/migration/keeper/msg_server_claim_morse_account.go b/x/migration/keeper/msg_server_claim_morse_account.go index 1bf758e71..27c60bef7 100644 --- a/x/migration/keeper/msg_server_claim_morse_account.go +++ b/x/migration/keeper/msg_server_claim_morse_account.go @@ -3,8 +3,8 @@ package keeper import ( "context" + "github.com/cometbft/cometbft/crypto/ed25519" cosmostypes "github.com/cosmos/cosmos-sdk/types" - cosmoserrors "github.com/cosmos/cosmos-sdk/types/errors" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -18,18 +18,9 @@ func (k msgServer) ClaimMorseAccount(ctx context.Context, msg *migrationtypes.Ms return nil, status.Error(codes.InvalidArgument, err.Error()) } - shannonAccAddr, err := cosmostypes.AccAddressFromBech32(msg.ShannonDestAddress) - // DEV_NOTE: This SHOULD NEVER happen as the shannonDestAddress is validated - // in MsgClaimMorseAccount#ValidateBasic(). - if err != nil { - return nil, status.Error( - codes.InvalidArgument, - cosmoserrors.ErrInvalidAddress.Wrapf( - "failed to parse shannon destination address (%s): %s", - msg.ShannonDestAddress, err, - ).Error(), - ) - } + // DEV_NOTE: It is safe to use MustAccAddressFromBech32 here because the + // shannonDestAddress is validated in MsgClaimMorseAccount#ValidateBasic(). + shannonAccAddr := cosmostypes.MustAccAddressFromBech32(msg.ShannonDestAddress) // Ensure that a MorseClaimableAccount exists for the given morseSrcAddress. morseClaimableAccount, isFound := k.GetMorseClaimableAccount( @@ -59,6 +50,12 @@ func (k msgServer) ClaimMorseAccount(ctx context.Context, msg *migrationtypes.Ms ) } + // Validate the Morse signature. + publicKey := ed25519.PubKey(morseClaimableAccount.GetPublicKey()) + if err := msg.ValidateMorseSignature(publicKey); err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + // Set ShannonDestAddress & ClaimedAtHeight (claim). morseClaimableAccount.ShannonDestAddress = shannonAccAddr.String() morseClaimableAccount.ClaimedAtHeight = sdkCtx.BlockHeight() @@ -76,7 +73,7 @@ func (k msgServer) ClaimMorseAccount(ctx context.Context, msg *migrationtypes.Ms Add(morseClaimableAccount.SupplierStake) // Mint the totalTokens to the shannonDestAddress account balance. - if err = k.MintClaimedMorseTokens(ctx, shannonAccAddr, totalTokens); err != nil { + if err := k.MintClaimedMorseTokens(ctx, shannonAccAddr, totalTokens); err != nil { return nil, status.Error(codes.Internal, err.Error()) } @@ -87,7 +84,7 @@ func (k msgServer) ClaimMorseAccount(ctx context.Context, msg *migrationtypes.Ms MorseSrcAddress: msg.MorseSrcAddress, ClaimedBalance: totalTokens, } - if err = sdkCtx.EventManager().EmitTypedEvent(&event); err != nil { + if err := sdkCtx.EventManager().EmitTypedEvent(&event); err != nil { return nil, status.Error( codes.Internal, migrationtypes.ErrMorseAccountClaim.Wrapf( diff --git a/x/migration/keeper/msg_server_claim_morse_acount_test.go b/x/migration/keeper/msg_server_claim_morse_acount_test.go index edb204823..d0a01baef 100644 --- a/x/migration/keeper/msg_server_claim_morse_acount_test.go +++ b/x/migration/keeper/msg_server_claim_morse_acount_test.go @@ -42,7 +42,7 @@ func TestMsgServer_ClaimMorseAccount_Success(t *testing.T) { // Claim each MorseClaimableAccount. for morseAccountIdx, morseAccount := range accountState.Accounts { // Generate the corresponding morse private key using the account slice index as a seed. - morsePrivKey := testmigration.NewMorsePrivateKey(t, uint64(morseAccountIdx)) + morsePrivKey := testmigration.NewMorsePrivateKey(t, uint64(morseAccountIdx+1)) // Claim the MorseClaimableAccount. msgClaim, err := migrationtypes.NewMsgClaimMorseAccount( @@ -52,6 +52,9 @@ func TestMsgServer_ClaimMorseAccount_Success(t *testing.T) { ) require.NoError(t, err) + err = msgClaim.SignMorseSignature(morsePrivKey) + require.NoError(t, err) + msgClaimRes, err := srv.ClaimMorseAccount(ctx, msgClaim) require.NoError(t, err) diff --git a/x/migration/types/message_claim_morse_account.go b/x/migration/types/message_claim_morse_account.go index cc486a9e0..88039fe73 100644 --- a/x/migration/types/message_claim_morse_account.go +++ b/x/migration/types/message_claim_morse_account.go @@ -4,7 +4,7 @@ import ( "encoding/hex" errorsmod "cosmossdk.io/errors" - cometcrypto "github.com/cometbft/cometbft/crypto/ed25519" + cometcrypto "github.com/cometbft/cometbft/crypto" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/gogoproto/proto" @@ -37,10 +37,6 @@ func NewMsgClaimMorseAccount( } func (msg *MsgClaimMorseAccount) ValidateBasic() error { - if len(msg.MorseSignature) == 0 { - return ErrMorseAccountClaim.Wrap("morseSignature is empty") - } - if len(msg.MorseSrcAddress) != MorseAddressHexLengthBytes { return ErrMorseAccountClaim.Wrapf("invalid morseSrcAddress length (%d)", len(msg.MorseSrcAddress)) } @@ -50,3 +46,52 @@ func (msg *MsgClaimMorseAccount) ValidateBasic() error { } return nil } + +// SignMorseSignature signs the given MsgClaimMorseAccount with the given Morse private key. +func (msg *MsgClaimMorseAccount) SignMorseSignature(morsePrivKey cometcrypto.PrivKey) error { + signingMsgBz, err := msg.getSigningBytes() + if err != nil { + return err + } + + signatureBz, err := morsePrivKey.Sign(signingMsgBz) + if err != nil { + return err + } + + msg.MorseSignature = hex.EncodeToString(signatureBz) + return nil +} + +// ValidateMorseSignature validates the signature of the given MsgClaimMorseAccount +// matches the given Morse public key. +func (msg *MsgClaimMorseAccount) ValidateMorseSignature(morsePublicKey cometcrypto.PubKey) error { + // Validate the morse signature. + morseSignature, err := hex.DecodeString(msg.MorseSignature) + if err != nil { + return err + } + + signingMsgBz, err := msg.getSigningBytes() + if err != nil { + return err + } + + // Validate the morse signature. + if !morsePublicKey.VerifySignature(signingMsgBz, morseSignature) { + return ErrMorseAccountClaim.Wrapf("morseSignature is invalid") + } + + return nil +} + +// getSigningBytes returns the canonical byte representation of the MsgClaimMorseAccount +// which is used for signing and/or signature validation. +func (msg *MsgClaimMorseAccount) getSigningBytes() ([]byte, error) { + // Copy msg and clear the morse signature field (ONLY on the copy) to prevent + // it from being included in the signature validation. + signingMsg := *msg + signingMsg.MorseSignature = "" + + return proto.Marshal(&signingMsg) +} diff --git a/x/migration/types/message_claim_morse_account_test.go b/x/migration/types/message_claim_morse_account_test.go index a16d52cbe..fe3dd2f52 100644 --- a/x/migration/types/message_claim_morse_account_test.go +++ b/x/migration/types/message_claim_morse_account_test.go @@ -1,39 +1,42 @@ -package types +package types_test import ( + "encoding/hex" "testing" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/stretchr/testify/require" "github.com/pokt-network/poktroll/testutil/sample" + "github.com/pokt-network/poktroll/testutil/testmigration" + migrationtypes "github.com/pokt-network/poktroll/x/migration/types" ) func TestMsgClaimMorseAccount_ValidateBasic(t *testing.T) { tests := []struct { - name string - msg MsgClaimMorseAccount + desc string + msg migrationtypes.MsgClaimMorseAccount err error }{ { - name: "invalid ShannonDestAddress", - msg: MsgClaimMorseAccount{ + desc: "invalid ShannonDestAddress", + msg: migrationtypes.MsgClaimMorseAccount{ ShannonDestAddress: "invalid_address", MorseSrcAddress: sample.MorseAddressHex(), MorseSignature: "mock_signature", }, err: sdkerrors.ErrInvalidAddress, }, { - name: "invalid MorseSrcAddress", - msg: MsgClaimMorseAccount{ + desc: "invalid MorseSrcAddress", + msg: migrationtypes.MsgClaimMorseAccount{ ShannonDestAddress: sample.AccAddress(), MorseSrcAddress: "invalid_address", MorseSignature: "mock_signature", }, - err: ErrMorseAccountClaim, + err: migrationtypes.ErrMorseAccountClaim, }, { - name: "valid claim message", - msg: MsgClaimMorseAccount{ + desc: "valid claim message", + msg: migrationtypes.MsgClaimMorseAccount{ ShannonDestAddress: sample.AccAddress(), MorseSrcAddress: sample.MorseAddressHex(), MorseSignature: "mock_signature", @@ -41,7 +44,7 @@ func TestMsgClaimMorseAccount_ValidateBasic(t *testing.T) { }, } for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { + t.Run(tt.desc, func(t *testing.T) { err := tt.msg.ValidateBasic() if tt.err != nil { require.ErrorIs(t, err, tt.err) @@ -51,3 +54,33 @@ func TestMsgClaimMorseAccount_ValidateBasic(t *testing.T) { }) } } + +func TestMsgClaimMorseAccount_ValidateMorseSignature(t *testing.T) { + morsePrivKey := testmigration.NewMorsePrivateKey(t, 0) + morsePublicKey := morsePrivKey.PubKey() + + t.Run("invalid Morse signature", func(t *testing.T) { + msg := migrationtypes.MsgClaimMorseAccount{ + ShannonDestAddress: sample.AccAddress(), + MorseSrcAddress: sample.MorseAddressHex(), + MorseSignature: hex.EncodeToString([]byte("invalid_signature")), + } + + expectedErr := migrationtypes.ErrMorseAccountClaim.Wrapf("morseSignature is invalid") + err := msg.ValidateMorseSignature(morsePublicKey) + require.EqualError(t, err, expectedErr.Error()) + }) + + t.Run("valid Morse signature", func(t *testing.T) { + msg := migrationtypes.MsgClaimMorseAccount{ + ShannonDestAddress: sample.AccAddress(), + MorseSrcAddress: sample.MorseAddressHex(), + // MorseSignature: (intenionally omitted; set in #SignMorseSignature) + } + err := msg.SignMorseSignature(morsePrivKey) + require.NoError(t, err) + + err = msg.ValidateMorseSignature(morsePublicKey) + require.NoError(t, err) + }) +} From 5a17194bc9134a30b2c744b8809860dfc9e96b90 Mon Sep 17 00:00:00 2001 From: Bryan White Date: Thu, 20 Feb 2025 15:00:45 +0100 Subject: [PATCH 16/18] fix: test --- x/migration/keeper/msg_server_claim_morse_acount_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/migration/keeper/msg_server_claim_morse_acount_test.go b/x/migration/keeper/msg_server_claim_morse_acount_test.go index d0a01baef..07b0d511b 100644 --- a/x/migration/keeper/msg_server_claim_morse_acount_test.go +++ b/x/migration/keeper/msg_server_claim_morse_acount_test.go @@ -129,7 +129,7 @@ func TestMsgServer_ClaimMorseAccount_Error(t *testing.T) { expectedErr := status.Error( codes.InvalidArgument, migrationtypes.ErrMorseAccountClaim.Wrapf( - "morseSignature is empty", + "morseSignature is invalid", ).Error(), ) From 7ca2cfe9164f89b37dcfeaf421f3ac499c984514 Mon Sep 17 00:00:00 2001 From: Bryan White Date: Mon, 24 Feb 2025 12:33:36 +0100 Subject: [PATCH 17/18] fix: typo --- .../keeper/msg_server_import_morse_claimable_accounts_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/migration/keeper/msg_server_import_morse_claimable_accounts_test.go b/x/migration/keeper/msg_server_import_morse_claimable_accounts_test.go index 39fd22f27..e2ab7e96e 100644 --- a/x/migration/keeper/msg_server_import_morse_claimable_accounts_test.go +++ b/x/migration/keeper/msg_server_import_morse_claimable_accounts_test.go @@ -80,8 +80,8 @@ func TestMsgServer_ImportMorseClaimableAccounts_ErrorAlreadySet(t *testing.T) { k.SetMorseClaimableAccount(ctx, *accountState.Accounts[0]) // Set up the MsgImportMorseClaimableAccounts to fail. - morseClaimableAccounts = k.GetAllMorseClaimableAccounts(ctx) - require.Equal(t, numAccounts, len(morseClaimableAccounts)) + morseClaimableAccounts := k.GetAllMorseClaimableAccounts(ctx) + require.Equal(t, 1, len(morseClaimableAccounts)) for _, morseClaimableAccount := range morseClaimableAccounts { require.Equal(t, int64(0), morseClaimableAccount.ClaimedAtHeight) require.Equal(t, "", morseClaimableAccount.ShannonDestAddress) From c3e467130a6f14ab44e525df85da40fb443461e0 Mon Sep 17 00:00:00 2001 From: Bryan White Date: Mon, 24 Feb 2025 15:32:34 +0100 Subject: [PATCH 18/18] fix: linter error --- x/migration/types/errors.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/migration/types/errors.go b/x/migration/types/errors.go index f93d577d1..255ff25d2 100644 --- a/x/migration/types/errors.go +++ b/x/migration/types/errors.go @@ -8,7 +8,7 @@ import ( // x/migration module sentinel errors var ( - ErrInvalidSigner = sdkerrors.Register(ModuleName, 1100, "expected x/gov module account as the only signer for migration state import messages") + ErrInvalidSigner = sdkerrors.Register(ModuleName, 1100, "expected x/gov module account as the only signer for migration state import messages") ErrMorseAccountsImport = sdkerrors.Register(ModuleName, 1101, "unable to import morse claimable accounts") ErrMorseAccountClaim = sdkerrors.Register(ModuleName, 1102, "unable to claim morse account") )