diff --git a/proto/cosmos/auth/genesis.proto b/proto/cosmos/auth/genesis.proto new file mode 100644 index 000000000..1513a9ff7 --- /dev/null +++ b/proto/cosmos/auth/genesis.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; +package cosmos.auth; + +import "google/protobuf/any.proto"; +import "gogoproto/gogo.proto"; +import "cosmos/auth/auth.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/auth/types"; + +// GenesisState - all auth state that must be provided at genesis +message GenesisState { + Params params = 1 [ + (gogoproto.casttype) = "Params", + (gogoproto.nullable) = false + ]; + repeated google.protobuf.Any accounts = 2; +} diff --git a/simapp/simd/cmd/genaccounts.go b/simapp/simd/cmd/genaccounts.go index 5f4121ee9..00dbe6621 100644 --- a/simapp/simd/cmd/genaccounts.go +++ b/simapp/simd/cmd/genaccounts.go @@ -120,14 +120,25 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa authGenState := authtypes.GetGenesisStateFromAppState(cdc, appState) - if authGenState.Accounts.Contains(addr) { + accs, err := authtypes.UnpackAccounts(authGenState.Accounts) + if err != nil { + return fmt.Errorf("failed to get accounts from any: %w", err) + } + + if accs.Contains(addr) { return fmt.Errorf("cannot add account at existing address %s", addr) } // Add the new account to the set of genesis accounts and sanitize the // accounts afterwards. - authGenState.Accounts = append(authGenState.Accounts, genAccount) - authGenState.Accounts = authtypes.SanitizeGenesisAccounts(authGenState.Accounts) + accs = append(accs, genAccount) + accs = authtypes.SanitizeGenesisAccounts(accs) + + genAccs, err := authtypes.PackAccounts(accs) + if err != nil { + return fmt.Errorf("failed to convert accounts into any's: %w", err) + } + authGenState.Accounts = genAccs authGenStateBz, err := cdc.MarshalJSON(authGenState) if err != nil { diff --git a/simapp/simd/cmd/testnet.go b/simapp/simd/cmd/testnet.go index bdb329177..340478f1c 100644 --- a/simapp/simd/cmd/testnet.go +++ b/simapp/simd/cmd/testnet.go @@ -264,7 +264,12 @@ func initGenFiles( var authGenState authtypes.GenesisState cdc.MustUnmarshalJSON(appGenState[authtypes.ModuleName], &authGenState) - authGenState.Accounts = genAccounts + accounts, err := authtypes.PackAccounts(genAccounts) + if err != nil { + return err + } + + authGenState.Accounts = accounts appGenState[authtypes.ModuleName] = cdc.MustMarshalJSON(authGenState) // set the balances in the genesis state diff --git a/simapp/state.go b/simapp/state.go index 055a4bd73..24d15f451 100644 --- a/simapp/state.go +++ b/simapp/state.go @@ -154,8 +154,13 @@ func AppStateFromGenesisFileFn(r io.Reader, cdc *codec.Codec, genesisFile string privKey := secp256k1.GenPrivKeySecp256k1(privkeySeed) + a, ok := acc.GetCachedValue().(authtypes.AccountI) + if !ok { + panic("expected account") + } + // create simulator accounts - simAcc := simtypes.Account{PrivKey: privKey, PubKey: privKey.PubKey(), Address: acc.GetAddress()} + simAcc := simtypes.Account{PrivKey: privKey, PubKey: privKey.PubKey(), Address: a.GetAddress()} newAccs[i] = simAcc } diff --git a/testutil/network/util.go b/testutil/network/util.go index 4754bc795..59ec3dca4 100644 --- a/testutil/network/util.go +++ b/testutil/network/util.go @@ -136,7 +136,12 @@ func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalance var authGenState authtypes.GenesisState cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[authtypes.ModuleName], &authGenState) - authGenState.Accounts = genAccounts + accounts, err := authtypes.PackAccounts(genAccounts) + if err != nil { + return err + } + + authGenState.Accounts = accounts cfg.GenesisState[authtypes.ModuleName] = cfg.Codec.MustMarshalJSON(authGenState) // set the balances in the genesis state diff --git a/x/auth/genesis.go b/x/auth/genesis.go index 71a6413cf..a0a2a9600 100644 --- a/x/auth/genesis.go +++ b/x/auth/genesis.go @@ -12,9 +12,14 @@ import ( // a genesis port script to the new fee collector account func InitGenesis(ctx sdk.Context, ak keeper.AccountKeeper, data types.GenesisState) { ak.SetParams(ctx, data.Params) - data.Accounts = types.SanitizeGenesisAccounts(data.Accounts) - for _, a := range data.Accounts { + accounts, err := types.UnpackAccounts(data.Accounts) + if err != nil { + panic(err) + } + accounts = types.SanitizeGenesisAccounts(accounts) + + for _, a := range accounts { acc := ak.NewAccount(ctx, a) ak.SetAccount(ctx, acc) } diff --git a/x/auth/simulation/genesis_test.go b/x/auth/simulation/genesis_test.go index bbec0a479..e0ae05f87 100644 --- a/x/auth/simulation/genesis_test.go +++ b/x/auth/simulation/genesis_test.go @@ -45,28 +45,11 @@ func TestRandomizedGenState(t *testing.T) { require.Equal(t, uint64(0x1ff), authGenesis.Params.GetSigVerifyCostSecp256k1()) require.Equal(t, uint64(9), authGenesis.Params.GetTxSigLimit()) require.Equal(t, uint64(5), authGenesis.Params.GetTxSizeCostPerByte()) - require.Len(t, authGenesis.Accounts, 3) - require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", authGenesis.Accounts[2].GetAddress().String()) - require.Equal(t, uint64(0), authGenesis.Accounts[2].GetAccountNumber()) - require.Equal(t, uint64(0), authGenesis.Accounts[2].GetSequence()) -} - -// TestRandomizedGenState tests abnormal scenarios of applying RandomizedGenState. -func TestRandomizedGenState1(t *testing.T) { - cdc := codec.New() - - s := rand.NewSource(1) - r := rand.New(s) - - simState := module.SimulationState{ - AppParams: make(simtypes.AppParams), - Cdc: cdc, - Rand: r, - NumBonded: 3, - Accounts: simtypes.RandomAccounts(r, 3), - InitialStake: 1000, - GenState: make(map[string]json.RawMessage), - } - - require.Panicsf(t, func() { simulation.RandomizedGenState(&simState) }, "Unregistered interface types.GenesisAccount") + + genAccounts, err := types.UnpackAccounts(authGenesis.Accounts) + require.NoError(t, err) + require.Len(t, genAccounts, 3) + require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", genAccounts[2].GetAddress().String()) + require.Equal(t, uint64(0), genAccounts[2].GetAccountNumber()) + require.Equal(t, uint64(0), genAccounts[2].GetSequence()) } diff --git a/x/auth/types/genesis.go b/x/auth/types/genesis.go index 6e6631e1e..7f76f22f9 100644 --- a/x/auth/types/genesis.go +++ b/x/auth/types/genesis.go @@ -6,22 +6,36 @@ import ( "sort" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + proto "github.com/gogo/protobuf/proto" ) -// GenesisState - all auth state that must be provided at genesis -type GenesisState struct { - Params Params `json:"params" yaml:"params"` - Accounts GenesisAccounts `json:"accounts" yaml:"accounts"` -} +var _ types.UnpackInterfacesMessage = GenesisState{} // NewGenesisState - Create a new genesis state func NewGenesisState(params Params, accounts GenesisAccounts) GenesisState { + genAccounts, err := PackAccounts(accounts) + if err != nil { + panic(err) + } return GenesisState{ Params: params, - Accounts: accounts, + Accounts: genAccounts, } } +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (g GenesisState) UnpackInterfaces(unpacker types.AnyUnpacker) error { + for _, any := range g.Accounts { + var account GenesisAccount + err := unpacker.UnpackAny(any, &account) + if err != nil { + return err + } + } + return nil +} + // DefaultGenesisState - Return a default genesis state func DefaultGenesisState() GenesisState { return NewGenesisState(DefaultParams(), GenesisAccounts{}) @@ -46,7 +60,12 @@ func ValidateGenesis(data GenesisState) error { return err } - return ValidateGenAccounts(data.Accounts) + genAccs, err := UnpackAccounts(data.Accounts) + if err != nil { + return err + } + + return ValidateGenAccounts(genAccs) } // SanitizeGenesisAccounts sorts accounts and coin sets. @@ -89,8 +108,44 @@ func (GenesisAccountIterator) IterateGenesisAccounts( cdc codec.Marshaler, appGenesis map[string]json.RawMessage, cb func(AccountI) (stop bool), ) { for _, genAcc := range GetGenesisStateFromAppState(cdc, appGenesis).Accounts { - if cb(genAcc) { + acc, ok := genAcc.GetCachedValue().(AccountI) + if !ok { + panic("expected account") + } + if cb(acc) { break } } } + +// PackAccounts converts GenesisAccounts to Any slice +func PackAccounts(accounts GenesisAccounts) ([]*types.Any, error) { + accountsAny := make([]*types.Any, len(accounts)) + for i, acc := range accounts { + msg, ok := acc.(proto.Message) + if !ok { + return nil, fmt.Errorf("cannot proto marshal %T", acc) + } + any, err := types.NewAnyWithValue(msg) + if err != nil { + return nil, err + } + accountsAny[i] = any + } + + return accountsAny, nil +} + +// UnpackAccounts converts Any slice to GenesisAccounts +func UnpackAccounts(accountsAny []*types.Any) (GenesisAccounts, error) { + accounts := make(GenesisAccounts, len(accountsAny)) + for i, any := range accountsAny { + acc, ok := any.GetCachedValue().(GenesisAccount) + if !ok { + return nil, fmt.Errorf("expected genesis account") + } + accounts[i] = acc + } + + return accounts, nil +} diff --git a/x/auth/types/genesis.pb.go b/x/auth/types/genesis.pb.go new file mode 100644 index 000000000..02ffbc243 --- /dev/null +++ b/x/auth/types/genesis.pb.go @@ -0,0 +1,390 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/auth/genesis.proto + +package types + +import ( + fmt "fmt" + types "github.com/cosmos/cosmos-sdk/codec/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GenesisState - all auth state that must be provided at genesis +type GenesisState struct { + Params Params `protobuf:"bytes,1,opt,name=params,proto3,casttype=Params" json:"params"` + Accounts []*types.Any `protobuf:"bytes,2,rep,name=accounts,proto3" json:"accounts,omitempty"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_eb73f4d82d582a1f, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +func (m *GenesisState) GetAccounts() []*types.Any { + if m != nil { + return m.Accounts + } + return nil +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "cosmos.auth.GenesisState") +} + +func init() { proto.RegisterFile("cosmos/auth/genesis.proto", fileDescriptor_eb73f4d82d582a1f) } + +var fileDescriptor_eb73f4d82d582a1f = []byte{ + // 246 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xce, 0x2f, 0xce, + 0xcd, 0x2f, 0xd6, 0x4f, 0x2c, 0x2d, 0xc9, 0xd0, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, + 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x86, 0x48, 0xe9, 0x81, 0xa4, 0xa4, 0x24, 0xd3, 0xf3, + 0xf3, 0xd3, 0x73, 0x52, 0xf5, 0xc1, 0x52, 0x49, 0xa5, 0x69, 0xfa, 0x89, 0x79, 0x95, 0x10, 0x75, + 0x52, 0x22, 0xe9, 0xf9, 0xe9, 0xf9, 0x60, 0xa6, 0x3e, 0x88, 0x05, 0x15, 0x15, 0x43, 0x36, 0x18, + 0x44, 0x40, 0xc4, 0x95, 0x6a, 0xb9, 0x78, 0xdc, 0x21, 0xd6, 0x04, 0x97, 0x24, 0x96, 0xa4, 0x0a, + 0x59, 0x73, 0xb1, 0x15, 0x24, 0x16, 0x25, 0xe6, 0x16, 0x4b, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x1b, + 0x09, 0xeb, 0x21, 0x59, 0xab, 0x17, 0x00, 0x96, 0x72, 0xe2, 0x3b, 0x71, 0x4f, 0x9e, 0xe1, 0xd7, + 0x3d, 0x79, 0x36, 0x08, 0x3f, 0x08, 0xaa, 0x45, 0xc8, 0x80, 0x8b, 0x23, 0x31, 0x39, 0x39, 0xbf, + 0x34, 0xaf, 0xa4, 0x58, 0x82, 0x49, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x44, 0x0f, 0xe2, 0x50, 0x3d, + 0x98, 0x43, 0xf5, 0x1c, 0xf3, 0x2a, 0x83, 0xe0, 0xaa, 0x9c, 0x9c, 0x4f, 0x3c, 0x92, 0x63, 0xbc, + 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, + 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x33, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, + 0x57, 0x1f, 0xea, 0x76, 0x08, 0xa5, 0x5b, 0x9c, 0x92, 0xad, 0x5f, 0x01, 0xf1, 0x48, 0x49, 0x65, + 0x41, 0x6a, 0x71, 0x12, 0x1b, 0xd8, 0x70, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x47, 0xda, + 0x47, 0x7b, 0x3d, 0x01, 0x00, 0x00, +} + +func (m *GenesisState) 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 *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Accounts) > 0 { + for iNdEx := len(m.Accounts) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Accounts[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovGenesis(uint64(l)) + if len(m.Accounts) > 0 { + for _, e := range m.Accounts { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) 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 ErrIntOverflowGenesis + } + 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: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Accounts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Accounts = append(m.Accounts, &types.Any{}) + if err := m.Accounts[len(m.Accounts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/auth/types/genesis_test.go b/x/auth/types/genesis_test.go index d42467857..783e44fd0 100644 --- a/x/auth/types/genesis_test.go +++ b/x/auth/types/genesis_test.go @@ -4,9 +4,11 @@ import ( "encoding/json" "testing" + proto "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto/ed25519" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/types" ) @@ -55,7 +57,9 @@ func TestGenesisAccountIterator(t *testing.T) { genAccounts := types.GenesisAccounts{acc1, acc2} authGenState := types.DefaultGenesisState() - authGenState.Accounts = genAccounts + accounts, err := types.PackAccounts(genAccounts) + require.NoError(t, err) + authGenState.Accounts = accounts appGenesis := make(map[string]json.RawMessage) authGenStateBz, err := appCodec.MarshalJSON(authGenState) @@ -75,3 +79,56 @@ func TestGenesisAccountIterator(t *testing.T) { require.Equal(t, addresses[0], acc1.GetAddress()) require.Equal(t, addresses[1], acc2.GetAddress()) } + +func TestPackAccountsAny(t *testing.T) { + var ( + accounts []*codectypes.Any + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + { + "expected genesis account", + func() { + accounts = []*codectypes.Any{&codectypes.Any{}} + }, + false, + }, + { + "success", + func() { + genAccounts := types.GenesisAccounts{&types.BaseAccount{}} + accounts = make([]*codectypes.Any, len(genAccounts)) + + for i, a := range genAccounts { + msg, ok := a.(proto.Message) + require.Equal(t, ok, true) + any, err := codectypes.NewAnyWithValue(msg) + require.NoError(t, err) + accounts[i] = any + } + }, + true, + }, + } + + for _, tc := range testCases { + t.Run(tc.msg, func(t *testing.T) { + tc.malleate() + + res, err := types.UnpackAccounts(accounts) + + if tc.expPass { + require.NoError(t, err) + require.NotNil(t, res) + require.Equal(t, len(res), len(accounts)) + } else { + require.Error(t, err) + require.Nil(t, res) + } + }) + } +}