From f0db6bc6befb53d72b10862f72b12bb3959c0d5d Mon Sep 17 00:00:00 2001 From: ryanchristo <12519942+ryanchristo@users.noreply.github.com> Date: Mon, 12 Dec 2022 11:23:06 -0800 Subject: [PATCH 1/8] fix: register gov and group amino codec --- types/module/testutil/codec.go | 43 +++++++++++++++++++++++++++ x/auth/types/codec.go | 8 +++-- x/auth/vesting/types/codec.go | 8 +++-- x/authz/codec.go | 8 +++-- x/bank/types/codec.go | 8 +++-- x/crisis/types/codec.go | 8 +++-- x/distribution/types/codec.go | 9 ++++-- x/evidence/types/codec.go | 8 +++-- x/feegrant/codec.go | 8 +++-- x/gov/codec/cdc.go | 18 +++++++++++ x/gov/codec/doc.go | 16 ++++++++++ x/gov/simulation/operations_test.go | 9 +++--- x/gov/types/v1/codec.go | 20 ++++--------- x/gov/types/v1/msgs.go | 9 +++--- x/gov/types/v1/msgs_test.go | 37 +++++++++++++++++------ x/gov/types/v1beta1/codec.go | 18 ++++------- x/gov/types/v1beta1/msgs.go | 9 +++--- x/group/codec.go | 22 +++++--------- x/group/codec/cdc.go | 18 +++++++++++ x/group/codec/doc.go | 16 ++++++++++ x/group/module/module.go | 4 ++- x/group/msgs.go | 29 +++++++++--------- x/group/msgs_test.go | 43 +++++++++++++++++++++++++-- x/group/simulation/operations_test.go | 29 +++++++++--------- x/mint/types/codec.go | 23 ++++++++++++-- x/slashing/types/codec.go | 8 +++-- x/staking/types/codec.go | 8 +++-- x/upgrade/types/codec.go | 9 ++++-- 28 files changed, 337 insertions(+), 116 deletions(-) create mode 100644 types/module/testutil/codec.go create mode 100644 x/gov/codec/cdc.go create mode 100644 x/gov/codec/doc.go create mode 100644 x/group/codec/cdc.go create mode 100644 x/group/codec/doc.go diff --git a/types/module/testutil/codec.go b/types/module/testutil/codec.go new file mode 100644 index 000000000000..b54085c584e7 --- /dev/null +++ b/types/module/testutil/codec.go @@ -0,0 +1,43 @@ +package testutil + +import ( + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/std" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/auth/tx" +) + +// TestEncodingConfig defines an encoding configuration that is used for testing +// purposes. Note, MakeTestEncodingConfig takes a series of AppModuleBasic types +// which should only contain the relevant module being tested and any potential +// dependencies. +type TestEncodingConfig struct { + InterfaceRegistry types.InterfaceRegistry + Codec codec.Codec + TxConfig client.TxConfig + Amino *codec.LegacyAmino +} + +func MakeTestEncodingConfig(modules ...module.AppModuleBasic) TestEncodingConfig { + cdc := codec.NewLegacyAmino() + interfaceRegistry := types.NewInterfaceRegistry() + codec := codec.NewProtoCodec(interfaceRegistry) + + encCfg := TestEncodingConfig{ + InterfaceRegistry: interfaceRegistry, + Codec: codec, + TxConfig: tx.NewTxConfig(codec, tx.DefaultSignModes), + Amino: cdc, + } + + mb := module.NewBasicManager(modules...) + + std.RegisterLegacyAminoCodec(encCfg.Amino) + std.RegisterInterfaces(encCfg.InterfaceRegistry) + mb.RegisterLegacyAminoCodec(encCfg.Amino) + mb.RegisterInterfaces(encCfg.InterfaceRegistry) + + return encCfg +} diff --git a/x/auth/types/codec.go b/x/auth/types/codec.go index 29561dfe018c..da4afe001d2c 100644 --- a/x/auth/types/codec.go +++ b/x/auth/types/codec.go @@ -7,6 +7,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" + groupcodec "github.com/cosmos/cosmos-sdk/x/group/codec" ) // RegisterLegacyAminoCodec registers the account interfaces and concrete types on the @@ -49,7 +51,9 @@ func init() { cryptocodec.RegisterCrypto(amino) sdk.RegisterLegacyAminoCodec(amino) - // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be - // used to properly serialize MsgGrant and MsgExec instances + // Register all Amino interfaces and concrete types on the authz and gov Amino codec so that this can later be + // used to properly serialize MsgGrant, MsgExec and MsgSubmitProposal instances RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) } diff --git a/x/auth/vesting/types/codec.go b/x/auth/vesting/types/codec.go index 270116671e91..7b2b33f58eab 100644 --- a/x/auth/vesting/types/codec.go +++ b/x/auth/vesting/types/codec.go @@ -10,6 +10,8 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported" authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" + groupcodec "github.com/cosmos/cosmos-sdk/x/group/codec" ) // RegisterLegacyAminoCodec registers the vesting interfaces and concrete types on the @@ -74,7 +76,9 @@ func init() { cryptocodec.RegisterCrypto(amino) sdk.RegisterLegacyAminoCodec(amino) - // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be - // used to properly serialize MsgGrant and MsgExec instances + // Register all Amino interfaces and concrete types on the authz and gov Amino codec so that this can later be + // used to properly serialize MsgGrant, MsgExec and MsgSubmitProposal instances RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) } diff --git a/x/authz/codec.go b/x/authz/codec.go index 77a6fa24e4f9..acc57f9691b5 100644 --- a/x/authz/codec.go +++ b/x/authz/codec.go @@ -7,6 +7,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" + groupcodec "github.com/cosmos/cosmos-sdk/x/group/codec" ) // RegisterLegacyAminoCodec registers the necessary x/authz interfaces and concrete types @@ -38,7 +40,9 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { } func init() { - // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be - // used to properly serialize MsgGrant and MsgExec instances + // Register all Amino interfaces and concrete types on the authz and gov Amino codec so that this can later be + // used to properly serialize MsgGrant, MsgExec and MsgSubmitProposal instances RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) } diff --git a/x/bank/types/codec.go b/x/bank/types/codec.go index a4107c1cfdb6..09e110ec1152 100644 --- a/x/bank/types/codec.go +++ b/x/bank/types/codec.go @@ -9,6 +9,8 @@ import ( "github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/x/authz" authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" + groupcodec "github.com/cosmos/cosmos-sdk/x/group/codec" ) // RegisterLegacyAminoCodec registers the necessary x/bank interfaces and concrete types @@ -42,7 +44,9 @@ func init() { cryptocodec.RegisterCrypto(amino) sdk.RegisterLegacyAminoCodec(amino) - // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be - // used to properly serialize MsgGrant and MsgExec instances + // Register all Amino interfaces and concrete types on the authz and gov Amino codec so that this can later be + // used to properly serialize MsgGrant, MsgExec and MsgSubmitProposal instances RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) } diff --git a/x/crisis/types/codec.go b/x/crisis/types/codec.go index 324ef56891ea..cc50fe383ae5 100644 --- a/x/crisis/types/codec.go +++ b/x/crisis/types/codec.go @@ -8,6 +8,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" + groupcodec "github.com/cosmos/cosmos-sdk/x/group/codec" ) // RegisterLegacyAminoCodec registers the necessary x/crisis interfaces and concrete types @@ -34,7 +36,9 @@ func init() { cryptocodec.RegisterCrypto(amino) sdk.RegisterLegacyAminoCodec(amino) - // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be - // used to properly serialize MsgGrant and MsgExec instances + // Register all Amino interfaces and concrete types on the authz and gov Amino codec so that this can later be + // used to properly serialize MsgGrant, MsgExec and MsgSubmitProposal instances RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) } diff --git a/x/distribution/types/codec.go b/x/distribution/types/codec.go index 0bff07d87340..6127bca7d551 100644 --- a/x/distribution/types/codec.go +++ b/x/distribution/types/codec.go @@ -8,7 +8,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + groupcodec "github.com/cosmos/cosmos-sdk/x/group/codec" ) // RegisterLegacyAminoCodec registers the necessary x/distribution interfaces and concrete types @@ -47,7 +49,10 @@ func init() { cryptocodec.RegisterCrypto(amino) sdk.RegisterLegacyAminoCodec(amino) - // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be - // used to properly serialize MsgGrant and MsgExec instances + // Register all Amino interfaces and concrete types on the authz and gov Amino codec + // so that this can later be used to properly serialize MsgGrant and MsgExec + // instances. RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) } diff --git a/x/evidence/types/codec.go b/x/evidence/types/codec.go index 19dcd12cbee9..4ea3ef1ea8e2 100644 --- a/x/evidence/types/codec.go +++ b/x/evidence/types/codec.go @@ -9,6 +9,8 @@ import ( "github.com/cosmos/cosmos-sdk/types/msgservice" authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" "github.com/cosmos/cosmos-sdk/x/evidence/exported" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" + groupcodec "github.com/cosmos/cosmos-sdk/x/group/codec" ) // RegisterLegacyAminoCodec registers all the necessary types and interfaces for the @@ -40,7 +42,9 @@ func init() { cryptocodec.RegisterCrypto(amino) sdk.RegisterLegacyAminoCodec(amino) - // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be - // used to properly serialize MsgGrant and MsgExec instances + // Register all Amino interfaces and concrete types on the authz and gov Amino codec so that this can later be + // used to properly serialize MsgGrant, MsgExec and MsgSubmitProposal instances RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) } diff --git a/x/feegrant/codec.go b/x/feegrant/codec.go index 0fd6eaeb9e7f..5007271a7125 100644 --- a/x/feegrant/codec.go +++ b/x/feegrant/codec.go @@ -8,6 +8,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" + groupcodec "github.com/cosmos/cosmos-sdk/x/group/codec" ) // RegisterLegacyAminoCodec registers the necessary x/feegrant interfaces and concrete types @@ -57,7 +59,9 @@ func init() { cryptocodec.RegisterCrypto(amino) sdk.RegisterLegacyAminoCodec(amino) - // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be - // used to properly serialize MsgGrant and MsgExec instances + // Register all Amino interfaces and concrete types on the authz and gov Amino codec so that this can later be + // used to properly serialize MsgGrant, MsgExec and MsgSubmitProposal instances RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) } diff --git a/x/gov/codec/cdc.go b/x/gov/codec/cdc.go new file mode 100644 index 000000000000..520e435afd69 --- /dev/null +++ b/x/gov/codec/cdc.go @@ -0,0 +1,18 @@ +package codec + +import ( + "github.com/cosmos/cosmos-sdk/codec" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var ( + Amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewAminoCodec(Amino) +) + +func init() { + cryptocodec.RegisterCrypto(Amino) + codec.RegisterEvidences(Amino) + sdk.RegisterLegacyAminoCodec(Amino) +} diff --git a/x/gov/codec/doc.go b/x/gov/codec/doc.go new file mode 100644 index 000000000000..182c2654710c --- /dev/null +++ b/x/gov/codec/doc.go @@ -0,0 +1,16 @@ +/* +Package codec provides a singleton instance of Amino codec that should be used to register +any concrete type that can later be referenced inside a MsgSubmitProposal instance so that they +can be (de)serialized properly. +Amino types should be ideally registered inside this codec within the init function of each module's +codec.go file as follows: + + func init() { + // ... + RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) + } + +The codec instance is put inside this package and not the x/gov/types package in order to avoid any dependency cycle. +*/ +package codec diff --git a/x/gov/simulation/operations_test.go b/x/gov/simulation/operations_test.go index 59c19d870707..5261d7e87505 100644 --- a/x/gov/simulation/operations_test.go +++ b/x/gov/simulation/operations_test.go @@ -15,6 +15,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/bank/testutil" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" "github.com/cosmos/cosmos-sdk/x/gov/simulation" "github.com/cosmos/cosmos-sdk/x/gov/types" v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" @@ -114,7 +115,7 @@ func TestSimulateMsgSubmitProposal(t *testing.T) { require.NoError(t, err) var msg v1.MsgSubmitProposal - err = v1.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = govcodec.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) require.NoError(t, err) require.True(t, operationMsg.OK) @@ -161,7 +162,7 @@ func TestSimulateMsgDeposit(t *testing.T) { require.NoError(t, err) var msg v1.MsgDeposit - err = v1.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = govcodec.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) require.NoError(t, err) require.True(t, operationMsg.OK) @@ -207,7 +208,7 @@ func TestSimulateMsgVote(t *testing.T) { require.NoError(t, err) var msg v1.MsgVote - v1.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + govcodec.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) require.True(t, operationMsg.OK) require.Equal(t, uint64(1), msg.ProposalId) @@ -250,7 +251,7 @@ func TestSimulateMsgVoteWeighted(t *testing.T) { require.NoError(t, err) var msg v1.MsgVoteWeighted - v1.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + govcodec.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) require.True(t, operationMsg.OK) require.Equal(t, uint64(1), msg.ProposalId) diff --git a/x/gov/types/v1/codec.go b/x/gov/types/v1/codec.go index 327094960d7b..095cf4ea8baa 100644 --- a/x/gov/types/v1/codec.go +++ b/x/gov/types/v1/codec.go @@ -4,11 +4,11 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/legacy" codectypes "github.com/cosmos/cosmos-sdk/codec/types" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" - "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" + groupcodec "github.com/cosmos/cosmos-sdk/x/group/codec" ) // RegisterLegacyAminoCodec registers all the necessary types and interfaces for the @@ -33,18 +33,10 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) } -var ( - amino = codec.NewLegacyAmino() - ModuleCdc = codec.NewAminoCodec(amino) -) - func init() { - RegisterLegacyAminoCodec(amino) - v1beta1.RegisterLegacyAminoCodec(amino) - cryptocodec.RegisterCrypto(amino) - sdk.RegisterLegacyAminoCodec(amino) - - // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be - // used to properly serialize MsgGrant and MsgExec instances + // Register all Amino interfaces and concrete types on the authz and gov Amino codec so that this can later be + // used to properly serialize MsgGrant, MsgExec and MsgSubmitProposal instances RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) } diff --git a/x/gov/types/v1/msgs.go b/x/gov/types/v1/msgs.go index dd83bf5dfa47..6bb357741f83 100644 --- a/x/gov/types/v1/msgs.go +++ b/x/gov/types/v1/msgs.go @@ -7,6 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" sdktx "github.com/cosmos/cosmos-sdk/types/tx" + "github.com/cosmos/cosmos-sdk/x/gov/codec" "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" ) @@ -83,7 +84,7 @@ func (m MsgSubmitProposal) ValidateBasic() error { // GetSignBytes implements Msg func (m MsgSubmitProposal) GetSignBytes() []byte { - bz := ModuleCdc.MustMarshalJSON(&m) + bz := codec.ModuleCdc.MustMarshalJSON(&m) return sdk.MustSortJSON(bz) } @@ -129,7 +130,7 @@ func (msg MsgDeposit) ValidateBasic() error { // GetSignBytes implements Msg func (msg MsgDeposit) GetSignBytes() []byte { - bz := ModuleCdc.MustMarshalJSON(&msg) + bz := codec.ModuleCdc.MustMarshalJSON(&msg) return sdk.MustSortJSON(bz) } @@ -166,7 +167,7 @@ func (msg MsgVote) ValidateBasic() error { // GetSignBytes implements Msg func (msg MsgVote) GetSignBytes() []byte { - bz := ModuleCdc.MustMarshalJSON(&msg) + bz := codec.ModuleCdc.MustMarshalJSON(&msg) return sdk.MustSortJSON(bz) } @@ -228,7 +229,7 @@ func (msg MsgVoteWeighted) ValidateBasic() error { // GetSignBytes implements Msg func (msg MsgVoteWeighted) GetSignBytes() []byte { - bz := ModuleCdc.MustMarshalJSON(&msg) + bz := codec.ModuleCdc.MustMarshalJSON(&msg) return sdk.MustSortJSON(bz) } diff --git a/x/gov/types/v1/msgs_test.go b/x/gov/types/v1/msgs_test.go index ad53ac5bf43e..ee4214270a96 100644 --- a/x/gov/types/v1/msgs_test.go +++ b/x/gov/types/v1/msgs_test.go @@ -1,8 +1,10 @@ package v1_test import ( + "fmt" "testing" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/stretchr/testify/require" sdk "github.com/cosmos/cosmos-sdk/types" @@ -169,13 +171,30 @@ func TestMsgSubmitProposal_ValidateBasic(t *testing.T) { // this tests that Amino JSON MsgSubmitProposal.GetSignBytes() still works with Content as Any using the ModuleCdc func TestMsgSubmitProposal_GetSignBytes(t *testing.T) { - proposal := []sdk.Msg{v1.NewMsgVote(addrs[0], 1, v1.OptionYes, "")} - msg, err := v1.NewMsgSubmitProposal(proposal, sdk.NewCoins(), sdk.AccAddress{}.String(), "") - require.NoError(t, err) - var bz []byte - require.NotPanics(t, func() { - bz = msg.GetSignBytes() - }) - require.Equal(t, "{\"type\":\"cosmos-sdk/v1/MsgSubmitProposal\",\"value\":{\"initial_deposit\":[],\"messages\":[{\"type\":\"cosmos-sdk/v1/MsgVote\",\"value\":{\"option\":1,\"proposal_id\":\"1\",\"voter\":\"cosmos1w3jhxap3gempvr\"}}]}}", - string(bz)) + testcases := []struct { + name string + proposal []sdk.Msg + expSignBz string + }{ + { + "MsgVote", []sdk.Msg{v1.NewMsgVote(addrs[0], 1, v1.OptionYes, "")}, + `{"type":"cosmos-sdk/v1/MsgSubmitProposal","value":{"initial_deposit":[],"messages":[{"type":"cosmos-sdk/v1/MsgVote","value":{"option":1,"proposal_id":"1","voter":"cosmos1w3jhxap3gempvr"}}]}}`, + }, + { + "MsgSend", []sdk.Msg{banktypes.NewMsgSend(addrs[0], addrs[0], sdk.NewCoins())}, + fmt.Sprintf(`{"type":"cosmos-sdk/v1/MsgSubmitProposal","value":{"initial_deposit":[],"messages":[{"type":"cosmos-sdk/MsgSend","value":{"amount":[],"from_address":"%s","to_address":"%s"}}]}}`, addrs[0], addrs[0]), + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + msg, err := v1.NewMsgSubmitProposal(tc.proposal, sdk.NewCoins(), sdk.AccAddress{}.String(), "") + require.NoError(t, err) + var bz []byte + require.NotPanics(t, func() { + bz = msg.GetSignBytes() + }) + require.Equal(t, tc.expSignBz, string(bz)) + }) + } } diff --git a/x/gov/types/v1beta1/codec.go b/x/gov/types/v1beta1/codec.go index f73f1082c5cd..1d8b2c54c332 100644 --- a/x/gov/types/v1beta1/codec.go +++ b/x/gov/types/v1beta1/codec.go @@ -4,10 +4,11 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/legacy" codectypes "github.com/cosmos/cosmos-sdk/codec/types" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" + groupcodec "github.com/cosmos/cosmos-sdk/x/group/codec" ) // RegisterLegacyAminoCodec registers all the necessary types and interfaces for the @@ -37,17 +38,10 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) } -var ( - amino = codec.NewLegacyAmino() - ModuleCdc = codec.NewAminoCodec(amino) -) - func init() { - RegisterLegacyAminoCodec(amino) - cryptocodec.RegisterCrypto(amino) - sdk.RegisterLegacyAminoCodec(amino) - - // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be - // used to properly serialize MsgGrant and MsgExec instances + // Register all Amino interfaces and concrete types on the authz and gov Amino codec so that this can later be + // used to properly serialize MsgGrant, MsgExec and MsgSubmitProposal instances RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) } diff --git a/x/gov/types/v1beta1/msgs.go b/x/gov/types/v1beta1/msgs.go index 54ad3ee40e7c..4f62ea2cfd4f 100644 --- a/x/gov/types/v1beta1/msgs.go +++ b/x/gov/types/v1beta1/msgs.go @@ -9,6 +9,7 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/gov/codec" "github.com/cosmos/cosmos-sdk/x/gov/types" ) @@ -110,7 +111,7 @@ func (m MsgSubmitProposal) ValidateBasic() error { // GetSignBytes implements Msg func (m MsgSubmitProposal) GetSignBytes() []byte { - bz := ModuleCdc.MustMarshalJSON(&m) + bz := codec.ModuleCdc.MustMarshalJSON(&m) return sdk.MustSortJSON(bz) } @@ -168,7 +169,7 @@ func (msg MsgDeposit) String() string { // GetSignBytes implements Msg func (msg MsgDeposit) GetSignBytes() []byte { - bz := ModuleCdc.MustMarshalJSON(&msg) + bz := codec.ModuleCdc.MustMarshalJSON(&msg) return sdk.MustSortJSON(bz) } @@ -211,7 +212,7 @@ func (msg MsgVote) String() string { // GetSignBytes implements Msg func (msg MsgVote) GetSignBytes() []byte { - bz := ModuleCdc.MustMarshalJSON(&msg) + bz := codec.ModuleCdc.MustMarshalJSON(&msg) return sdk.MustSortJSON(bz) } @@ -275,7 +276,7 @@ func (msg MsgVoteWeighted) String() string { // GetSignBytes implements Msg func (msg MsgVoteWeighted) GetSignBytes() []byte { - bz := ModuleCdc.MustMarshalJSON(&msg) + bz := codec.ModuleCdc.MustMarshalJSON(&msg) return sdk.MustSortJSON(bz) } diff --git a/x/group/codec.go b/x/group/codec.go index 32e1ec15c7cb..ef7f34e1f88d 100644 --- a/x/group/codec.go +++ b/x/group/codec.go @@ -1,19 +1,20 @@ package group import ( - "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/legacy" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" + groupcodec "github.com/cosmos/cosmos-sdk/x/group/codec" ) // RegisterLegacyAminoCodec registers all the necessary group module concrete // types and interfaces with the provided codec reference. // These types are used for Amino JSON serialization. -func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { +func RegisterLegacyAminoCodec(cdc *codectypes.LegacyAmino) { cdc.RegisterInterface((*DecisionPolicy)(nil), nil) cdc.RegisterConcrete(&ThresholdDecisionPolicy{}, "cosmos-sdk/ThresholdDecisionPolicy", nil) cdc.RegisterConcrete(&PercentageDecisionPolicy{}, "cosmos-sdk/PercentageDecisionPolicy", nil) @@ -62,17 +63,10 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { ) } -var ( - amino = codec.NewLegacyAmino() - ModuleCdc = codec.NewAminoCodec(amino) -) - func init() { - RegisterLegacyAminoCodec(amino) - cryptocodec.RegisterCrypto(amino) - sdk.RegisterLegacyAminoCodec(amino) - - // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be - // used to properly serialize MsgGrant and MsgExec instances + // Register all Amino interfaces and concrete types on the authz and gov Amino codec so that this can later be + // used to properly serialize MsgGrant, MsgExec and MsgSubmitProposal instances RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) } diff --git a/x/group/codec/cdc.go b/x/group/codec/cdc.go new file mode 100644 index 000000000000..520e435afd69 --- /dev/null +++ b/x/group/codec/cdc.go @@ -0,0 +1,18 @@ +package codec + +import ( + "github.com/cosmos/cosmos-sdk/codec" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var ( + Amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewAminoCodec(Amino) +) + +func init() { + cryptocodec.RegisterCrypto(Amino) + codec.RegisterEvidences(Amino) + sdk.RegisterLegacyAminoCodec(Amino) +} diff --git a/x/group/codec/doc.go b/x/group/codec/doc.go new file mode 100644 index 000000000000..efea67638778 --- /dev/null +++ b/x/group/codec/doc.go @@ -0,0 +1,16 @@ +/* +Package codec provides a singleton instance of Amino codec that should be used to register +any concrete type that can later be referenced inside a MsgSubmitProposal instance so that they +can be (de)serialized properly. +Amino types should be ideally registered inside this codec within the init function of each module's +codec.go file as follows: + + func init() { + // ... + RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) + } + +The codec instance is put inside this package and not the x/gov/types package in order to avoid any dependency cycle. +*/ +package codec diff --git a/x/group/module/module.go b/x/group/module/module.go index 800292789a31..3f45e66f2cba 100644 --- a/x/group/module/module.go +++ b/x/group/module/module.go @@ -94,7 +94,9 @@ func (AppModuleBasic) RegisterInterfaces(registry cdctypes.InterfaceRegistry) { } // RegisterLegacyAminoCodec registers the group module's types for the given codec. -func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {} +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + group.RegisterLegacyAminoCodec(cdc) +} // Name returns the group module's name. func (AppModule) Name() string { diff --git a/x/group/msgs.go b/x/group/msgs.go index 6cab5e3dfbfe..66128dd9c5f6 100644 --- a/x/group/msgs.go +++ b/x/group/msgs.go @@ -7,6 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/tx" + "github.com/cosmos/cosmos-sdk/x/group/codec" errors "github.com/cosmos/cosmos-sdk/x/group/errors" "github.com/cosmos/cosmos-sdk/x/group/internal/math" ) @@ -21,7 +22,7 @@ func (m MsgCreateGroup) Type() string { return sdk.MsgTypeURL(&m) } // GetSignBytes Implements Msg. func (m MsgCreateGroup) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) + return sdk.MustSortJSON(codec.ModuleCdc.MustMarshalJSON(&m)) } // GetSigners returns the expected signers for a MsgCreateGroup. @@ -71,7 +72,7 @@ func (m MsgUpdateGroupAdmin) Type() string { return sdk.MsgTypeURL(&m) } // GetSignBytes Implements Msg. func (m MsgUpdateGroupAdmin) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) + return sdk.MustSortJSON(codec.ModuleCdc.MustMarshalJSON(&m)) } // GetSigners returns the expected signers for a MsgUpdateGroupAdmin. @@ -119,7 +120,7 @@ func (m MsgUpdateGroupMetadata) Type() string { return sdk.MsgTypeURL(&m) } // GetSignBytes Implements Msg. func (m MsgUpdateGroupMetadata) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) + return sdk.MustSortJSON(codec.ModuleCdc.MustMarshalJSON(&m)) } // GetSigners returns the expected signers for a MsgUpdateGroupMetadata. @@ -158,7 +159,7 @@ func (m MsgUpdateGroupMembers) Type() string { return sdk.MsgTypeURL(&m) } // GetSignBytes Implements Msg. func (m MsgUpdateGroupMembers) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) + return sdk.MustSortJSON(codec.ModuleCdc.MustMarshalJSON(&m)) } var _ sdk.Msg = &MsgUpdateGroupMembers{} @@ -250,7 +251,7 @@ func (m MsgCreateGroupWithPolicy) Type() string { // GetSignBytes Implements Msg. func (m MsgCreateGroupWithPolicy) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) + return sdk.MustSortJSON(codec.ModuleCdc.MustMarshalJSON(&m)) } // GetSigners returns the expected signers for a MsgCreateGroupWithPolicy. @@ -288,7 +289,7 @@ func (m MsgCreateGroupPolicy) Type() string { return sdk.MsgTypeURL(&m) } // GetSignBytes Implements Msg. func (m MsgCreateGroupPolicy) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) + return sdk.MustSortJSON(codec.ModuleCdc.MustMarshalJSON(&m)) } // GetSigners returns the expected signers for a MsgCreateGroupPolicy. @@ -330,7 +331,7 @@ func (m MsgUpdateGroupPolicyAdmin) Type() string { return sdk.MsgTypeURL(&m) } // GetSignBytes Implements Msg. func (m MsgUpdateGroupPolicyAdmin) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) + return sdk.MustSortJSON(codec.ModuleCdc.MustMarshalJSON(&m)) } // GetSigners returns the expected signers for a MsgUpdateGroupPolicyAdmin. @@ -406,7 +407,7 @@ func (m MsgUpdateGroupPolicyDecisionPolicy) Type() string { // GetSignBytes Implements Msg. func (m MsgUpdateGroupPolicyDecisionPolicy) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) + return sdk.MustSortJSON(codec.ModuleCdc.MustMarshalJSON(&m)) } // GetSigners returns the expected signers for a MsgUpdateGroupPolicyDecisionPolicy. @@ -467,7 +468,7 @@ func (m MsgUpdateGroupPolicyMetadata) Type() string { return sdk.MsgTypeURL(&m) // GetSignBytes Implements Msg. func (m MsgUpdateGroupPolicyMetadata) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) + return sdk.MustSortJSON(codec.ModuleCdc.MustMarshalJSON(&m)) } // GetSigners returns the expected signers for a MsgUpdateGroupPolicyMetadata. @@ -573,7 +574,7 @@ func (m MsgSubmitProposal) Type() string { return sdk.MsgTypeURL(&m) } // GetSignBytes Implements Msg. func (m MsgSubmitProposal) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) + return sdk.MustSortJSON(codec.ModuleCdc.MustMarshalJSON(&m)) } // GetSigners returns the expected signers for a MsgSubmitProposal. @@ -665,7 +666,7 @@ func (m MsgWithdrawProposal) Type() string { return sdk.MsgTypeURL(&m) } // GetSignBytes Implements Msg. func (m MsgWithdrawProposal) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) + return sdk.MustSortJSON(codec.ModuleCdc.MustMarshalJSON(&m)) } // GetSigners returns the expected signers for a MsgWithdrawProposal. @@ -701,7 +702,7 @@ func (m MsgVote) Type() string { return sdk.MsgTypeURL(&m) } // GetSignBytes Implements Msg. func (m MsgVote) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) + return sdk.MustSortJSON(codec.ModuleCdc.MustMarshalJSON(&m)) } // GetSigners returns the expected signers for a MsgVote. @@ -741,7 +742,7 @@ func (m MsgExec) Type() string { return sdk.MsgTypeURL(&m) } // GetSignBytes Implements Msg. func (m MsgExec) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) + return sdk.MustSortJSON(codec.ModuleCdc.MustMarshalJSON(&m)) } // GetSigners returns the expected signers for a MsgExec. @@ -775,7 +776,7 @@ func (m MsgLeaveGroup) Type() string { return sdk.MsgTypeURL(&m) } // GetSignBytes Implements Msg func (m MsgLeaveGroup) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) + return sdk.MustSortJSON(codec.ModuleCdc.MustMarshalJSON(&m)) } // GetSigners returns the expected signers for a MsgLeaveGroup diff --git a/x/group/msgs_test.go b/x/group/msgs_test.go index 5242f6ca79b9..edd8f22c5ecb 100644 --- a/x/group/msgs_test.go +++ b/x/group/msgs_test.go @@ -1,13 +1,16 @@ package group_test import ( + "fmt" "testing" "time" - "github.com/stretchr/testify/require" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module/testutil" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/group" + "github.com/cosmos/cosmos-sdk/x/group/module" + "github.com/stretchr/testify/require" ) var ( @@ -962,6 +965,31 @@ func TestMsgSubmitProposal(t *testing.T) { } } +func TestMsgSubmitProposalGetSignBytes(t *testing.T) { + testcases := []struct { + name string + proposal []sdk.Msg + expSignBz string + }{ + { + "MsgSend", []sdk.Msg{banktypes.NewMsgSend(member1, member1, sdk.NewCoins())}, + fmt.Sprintf(`{"type":"cosmos-sdk/group/MsgSubmitProposal","value":{"messages":[{"type":"cosmos-sdk/MsgSend","value":{"amount":[],"from_address":"%s","to_address":"%s"}}],"proposers":[""]}}`, member1, member1), + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + msg, err := group.NewMsgSubmitProposal(sdk.AccAddress{}.String(), []string{sdk.AccAddress{}.String()}, tc.proposal, "", group.Exec_EXEC_UNSPECIFIED) + require.NoError(t, err) + var bz []byte + require.NotPanics(t, func() { + bz = msg.GetSignBytes() + }) + require.Equal(t, tc.expSignBz, string(bz)) + }) + } +} + func TestMsgVote(t *testing.T) { testCases := []struct { name string @@ -1165,3 +1193,14 @@ func TestMsgLeaveGroup(t *testing.T) { }) } } + +func TestAmino(t *testing.T) { + cdc := testutil.MakeTestEncodingConfig(module.AppModuleBasic{}) + + out, err := cdc.Amino.MarshalJSON(group.MsgSubmitProposal{Proposers: []string{member1.String()}}) + require.NoError(t, err) + require.Equal(t, + `{"type":"cosmos-sdk/group/MsgSubmitProposal","value":{"proposers":["cosmos1d4jk6cn9wgcsj540xq"]}}`, + string(out), + ) +} diff --git a/x/group/simulation/operations_test.go b/x/group/simulation/operations_test.go index 90476db47fd6..7a03303ed2a6 100644 --- a/x/group/simulation/operations_test.go +++ b/x/group/simulation/operations_test.go @@ -15,6 +15,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank/testutil" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/group" + groupcdc "github.com/cosmos/cosmos-sdk/x/group/codec" "github.com/cosmos/cosmos-sdk/x/group/simulation" ) @@ -115,7 +116,7 @@ func (suite *SimTestSuite) TestSimulateCreateGroup() { suite.Require().NoError(err) var msg group.MsgCreateGroup - err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = groupcdc.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().NoError(err) suite.Require().True(operationMsg.OK) suite.Require().Equal(acc.Address.String(), msg.Admin) @@ -144,7 +145,7 @@ func (suite *SimTestSuite) TestSimulateCreateGroupWithPolicy() { suite.Require().NoError(err) var msg group.MsgCreateGroupWithPolicy - err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = groupcdc.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().NoError(err) suite.Require().True(operationMsg.OK) suite.Require().Equal(acc.Address.String(), msg.Admin) @@ -186,7 +187,7 @@ func (suite *SimTestSuite) TestSimulateCreateGroupPolicy() { suite.Require().NoError(err) var msg group.MsgCreateGroupPolicy - err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = groupcdc.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().NoError(err) suite.Require().True(operationMsg.OK) suite.Require().Equal(acc.Address.String(), msg.Admin) @@ -239,7 +240,7 @@ func (suite *SimTestSuite) TestSimulateSubmitProposal() { suite.Require().NoError(err) var msg group.MsgSubmitProposal - err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = groupcdc.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().NoError(err) suite.Require().True(operationMsg.OK) suite.Require().Equal(groupPolicyRes.Address, msg.GroupPolicyAddress) @@ -305,7 +306,7 @@ func (suite *SimTestSuite) TestWithdrawProposal() { suite.Require().NoError(err) var msg group.MsgWithdrawProposal - err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = groupcdc.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().NoError(err) suite.Require().True(operationMsg.OK) suite.Require().Equal(addr, msg.Address) @@ -372,7 +373,7 @@ func (suite *SimTestSuite) TestSimulateVote() { suite.Require().NoError(err) var msg group.MsgVote - err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = groupcdc.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().NoError(err) suite.Require().True(operationMsg.OK) suite.Require().Equal(addr, msg.Voter) @@ -447,7 +448,7 @@ func (suite *SimTestSuite) TestSimulateExec() { suite.Require().NoError(err) var msg group.MsgExec - err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = groupcdc.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().NoError(err) suite.Require().True(operationMsg.OK) suite.Require().Equal(addr, msg.Executor) @@ -489,7 +490,7 @@ func (suite *SimTestSuite) TestSimulateUpdateGroupAdmin() { suite.Require().NoError(err) var msg group.MsgUpdateGroupAdmin - err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = groupcdc.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().NoError(err) suite.Require().True(operationMsg.OK) suite.Require().Equal(acc.Address.String(), msg.Admin) @@ -531,7 +532,7 @@ func (suite *SimTestSuite) TestSimulateUpdateGroupMetadata() { suite.Require().NoError(err) var msg group.MsgUpdateGroupMetadata - err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = groupcdc.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().NoError(err) suite.Require().True(operationMsg.OK) suite.Require().Equal(acc.Address.String(), msg.Admin) @@ -573,7 +574,7 @@ func (suite *SimTestSuite) TestSimulateUpdateGroupMembers() { suite.Require().NoError(err) var msg group.MsgUpdateGroupMembers - err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = groupcdc.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().NoError(err) suite.Require().True(operationMsg.OK) suite.Require().Equal(acc.Address.String(), msg.Admin) @@ -626,7 +627,7 @@ func (suite *SimTestSuite) TestSimulateUpdateGroupPolicyAdmin() { suite.Require().NoError(err) var msg group.MsgUpdateGroupPolicyAdmin - err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = groupcdc.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().NoError(err) suite.Require().True(operationMsg.OK) suite.Require().Equal(groupPolicyRes.Address, msg.GroupPolicyAddress) @@ -679,7 +680,7 @@ func (suite *SimTestSuite) TestSimulateUpdateGroupPolicyDecisionPolicy() { suite.Require().NoError(err) var msg group.MsgUpdateGroupPolicyDecisionPolicy - err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = groupcdc.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().NoError(err) suite.Require().True(operationMsg.OK) suite.Require().Equal(groupPolicyRes.Address, msg.GroupPolicyAddress) @@ -732,7 +733,7 @@ func (suite *SimTestSuite) TestSimulateUpdateGroupPolicyMetadata() { suite.Require().NoError(err) var msg group.MsgUpdateGroupPolicyMetadata - err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = groupcdc.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().NoError(err) suite.Require().True(operationMsg.OK) suite.Require().Equal(groupPolicyRes.Address, msg.GroupPolicyAddress) @@ -798,7 +799,7 @@ func (suite *SimTestSuite) TestSimulateLeaveGroup() { suite.Require().NoError(err) var msg group.MsgLeaveGroup - err = group.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) + err = groupcdc.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().NoError(err) suite.Require().True(operationMsg.OK) suite.Require().Equal(groupRes.GroupId, msg.GroupId) diff --git a/x/mint/types/codec.go b/x/mint/types/codec.go index a7067d90c2c5..0f798eb671b0 100644 --- a/x/mint/types/codec.go +++ b/x/mint/types/codec.go @@ -3,11 +3,30 @@ package types import ( "github.com/cosmos/cosmos-sdk/codec" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" + groupcodec "github.com/cosmos/cosmos-sdk/x/group/codec" ) -var amino = codec.NewLegacyAmino() +var ( + amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewAminoCodec(amino) +) func init() { + RegisterLegacyAminoCodec(amino) cryptocodec.RegisterCrypto(amino) - amino.Seal() + sdk.RegisterLegacyAminoCodec(amino) + + // Register all Amino interfaces and concrete types on the authz and gov Amino codec + // so that this can later be used to properly serialize MsgGrant and MsgExec instances. + RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) +} + +// RegisterLegacyAminoCodec registers concrete types on the LegacyAmino codec +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(Params{}, "cosmos-sdk/x/mint/Params", nil) } diff --git a/x/slashing/types/codec.go b/x/slashing/types/codec.go index d1b54a969ee1..b47172150b89 100644 --- a/x/slashing/types/codec.go +++ b/x/slashing/types/codec.go @@ -8,6 +8,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" + groupcodec "github.com/cosmos/cosmos-sdk/x/group/codec" ) // RegisterLegacyAminoCodec registers concrete types on LegacyAmino codec @@ -33,7 +35,9 @@ func init() { cryptocodec.RegisterCrypto(amino) sdk.RegisterLegacyAminoCodec(amino) - // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be - // used to properly serialize MsgGrant and MsgExec instances + // Register all Amino interfaces and concrete types on the authz and gov Amino codec so that this can later be + // used to properly serialize MsgGrant, MsgExec and MsgSubmitProposal instances RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) } diff --git a/x/staking/types/codec.go b/x/staking/types/codec.go index 558f2eb038ad..91bccbbcc453 100644 --- a/x/staking/types/codec.go +++ b/x/staking/types/codec.go @@ -9,6 +9,8 @@ import ( "github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/x/authz" authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" + groupcodec "github.com/cosmos/cosmos-sdk/x/group/codec" ) // RegisterLegacyAminoCodec registers the necessary x/staking interfaces and concrete types @@ -55,7 +57,9 @@ func init() { cryptocodec.RegisterCrypto(amino) sdk.RegisterLegacyAminoCodec(amino) - // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be - // used to properly serialize MsgGrant and MsgExec instances + // Register all Amino interfaces and concrete types on the authz and gov Amino codec so that this can later be + // used to properly serialize MsgGrant, MsgExec and MsgSubmitProposal instances RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) } diff --git a/x/upgrade/types/codec.go b/x/upgrade/types/codec.go index 0f852cc9a2a9..a663c35c6d48 100644 --- a/x/upgrade/types/codec.go +++ b/x/upgrade/types/codec.go @@ -8,7 +8,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + groupcodec "github.com/cosmos/cosmos-sdk/x/group/codec" ) // RegisterLegacyAminoCodec registers concrete types on the LegacyAmino codec @@ -45,7 +47,10 @@ func init() { cryptocodec.RegisterCrypto(amino) sdk.RegisterLegacyAminoCodec(amino) - // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be - // used to properly serialize MsgGrant and MsgExec instances + // Register all Amino interfaces and concrete types on the authz and gov Amino codec + // so that this can later be used to properly serialize MsgGrant and MsgExec + // instances. RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) } From cb7b2b2bec9c996e7f189504bf54b58e9547051e Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Wed, 19 Oct 2022 15:16:23 +0200 Subject: [PATCH 2/8] fix(group)!: Register types with Amino (#13592) * fix!(group): Register types with Amino * Chagenlog --- x/group/msgs_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/x/group/msgs_test.go b/x/group/msgs_test.go index edd8f22c5ecb..5b82d2de316f 100644 --- a/x/group/msgs_test.go +++ b/x/group/msgs_test.go @@ -5,12 +5,13 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module/testutil" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/group" "github.com/cosmos/cosmos-sdk/x/group/module" - "github.com/stretchr/testify/require" ) var ( @@ -972,7 +973,8 @@ func TestMsgSubmitProposalGetSignBytes(t *testing.T) { expSignBz string }{ { - "MsgSend", []sdk.Msg{banktypes.NewMsgSend(member1, member1, sdk.NewCoins())}, + "MsgSend", + []sdk.Msg{banktypes.NewMsgSend(member1, member1, sdk.NewCoins())}, fmt.Sprintf(`{"type":"cosmos-sdk/group/MsgSubmitProposal","value":{"messages":[{"type":"cosmos-sdk/MsgSend","value":{"amount":[],"from_address":"%s","to_address":"%s"}}],"proposers":[""]}}`, member1, member1), }, } From c5a1f2a40f5d227f47bf6833d9f223f34caf0d2e Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Thu, 8 Sep 2022 17:35:57 +0200 Subject: [PATCH 3/8] fix!: Fix gov amino codec (#13196) * fix!: Fix gov amino codec * changelog --- docs/core/encoding.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/core/encoding.md b/docs/core/encoding.md index 298ce752401c..f43689106820 100644 --- a/docs/core/encoding.md +++ b/docs/core/encoding.md @@ -67,18 +67,22 @@ Note, there are length-prefixed variants of the above functionality and this is typically used for when the data needs to be streamed or grouped together (e.g. `ResponseDeliverTx.Data`) -#### Authz authorizations +#### Authz authorizations and Gov proposals -Since the `MsgExec` message type can contain different messages instances, it is important that developers +Since authz's `MsgExec` and `MsgGrant` message types, as well as gov's `MsgSubmitProposal`, can contain different messages instances, it is important that developers add the following code inside the `init` method of their module's `codec.go` file: ```go -import authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" +import ( + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" +) init() { - // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be - // used to properly serialize MsgGrant and MsgExec instances + // Register all Amino interfaces and concrete types on the authz and gov Amino codec so that this can later be + // used to properly serialize MsgGrant, MsgExec and MsgSubmitProposal instances RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) } ``` From 638d47e9f321fa2295a3604b5e1e50f865be2479 Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Thu, 15 Sep 2022 19:06:43 +0200 Subject: [PATCH 4/8] fix!: Fix group amino codec (#13307) * fix!: Fix group amino codec * changelog --- docs/core/encoding.md | 6 ++++-- x/group/codec/doc.go | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/core/encoding.md b/docs/core/encoding.md index f43689106820..629fda49e2a3 100644 --- a/docs/core/encoding.md +++ b/docs/core/encoding.md @@ -67,15 +67,16 @@ Note, there are length-prefixed variants of the above functionality and this is typically used for when the data needs to be streamed or grouped together (e.g. `ResponseDeliverTx.Data`) -#### Authz authorizations and Gov proposals +#### Authz authorizations and Gov/Group proposals -Since authz's `MsgExec` and `MsgGrant` message types, as well as gov's `MsgSubmitProposal`, can contain different messages instances, it is important that developers +Since authz's `MsgExec` and `MsgGrant` message types, as well as gov's and group's `MsgSubmitProposal`, can contain different messages instances, it is important that developers add the following code inside the `init` method of their module's `codec.go` file: ```go import ( authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" + groupcodec "github.com/cosmos/cosmos-sdk/x/group/codec" ) init() { @@ -83,6 +84,7 @@ init() { // used to properly serialize MsgGrant, MsgExec and MsgSubmitProposal instances RegisterLegacyAminoCodec(authzcodec.Amino) RegisterLegacyAminoCodec(govcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) } ``` diff --git a/x/group/codec/doc.go b/x/group/codec/doc.go index efea67638778..182c2654710c 100644 --- a/x/group/codec/doc.go +++ b/x/group/codec/doc.go @@ -8,7 +8,7 @@ codec.go file as follows: func init() { // ... RegisterLegacyAminoCodec(govcodec.Amino) - RegisterLegacyAminoCodec(groupcodec.Amino) + RegisterLegacyAminoCodec(groupcodec.Amino) } The codec instance is put inside this package and not the x/gov/types package in order to avoid any dependency cycle. From eb0ee54e000c1c92470b57fc68abf22c33fdd5e9 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Tue, 27 Sep 2022 21:02:02 +0200 Subject: [PATCH 5/8] build(deps): bump go minimum version to go 1.19 (#13397) --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/cosmovisor-release.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/sims.yml | 8 ++++---- .github/workflows/test.yml | 12 ++++++------ Dockerfile | 2 +- README.md | 2 +- client/v2/go.mod | 2 +- contrib/images/simd-dlv/Dockerfile | 2 +- contrib/images/simd-env/Dockerfile | 2 +- contrib/rosetta/rosetta-ci/Dockerfile | 2 +- contrib/rosetta/rosetta-cli/Dockerfile | 2 +- core/go.mod | 2 +- cosmovisor/go.mod | 2 +- errors/go.mod | 2 +- go.mod | 2 +- math/go.mod | 2 +- orm/go.mod | 2 +- store/tools/ics23/go.mod | 2 +- 19 files changed, 27 insertions(+), 27 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 968b24c94448..67de44c531e2 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -25,7 +25,7 @@ jobs: uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v2 diff --git a/.github/workflows/cosmovisor-release.yml b/.github/workflows/cosmovisor-release.yml index 1a7100d5a780..f28ca050bfe7 100644 --- a/.github/workflows/cosmovisor-release.yml +++ b/.github/workflows/cosmovisor-release.yml @@ -13,7 +13,7 @@ jobs: fetch-depth: 0 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 # get 'v*.*.*' part from 'cosmovisor/v*.*.*' and save to $GITHUB_ENV - name: Set env run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/cosmovisor/}" >> $GITHUB_ENV diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 34095509f6e7..4d3bd45a5f3e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ jobs: - name: Install Go uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Unshallow run: git fetch --prune --unshallow - name: Create release diff --git a/.github/workflows/sims.yml b/.github/workflows/sims.yml index d7e97454a7b5..da9475595a32 100644 --- a/.github/workflows/sims.yml +++ b/.github/workflows/sims.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Display go version run: go version - run: make build @@ -51,7 +51,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Display go version run: go version - uses: actions/cache@v3 @@ -70,7 +70,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Display go version run: go version - uses: actions/cache@v3 @@ -89,7 +89,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Display go version run: go version - uses: actions/cache@v3 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b5234cc89eba..35c89c04ee96 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - uses: technote-space/get-diff-action@v6.0.1 id: git_diff with: @@ -48,7 +48,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - uses: technote-space/get-diff-action@v6.0.1 id: git_diff with: @@ -71,7 +71,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Create a file with all core Cosmos SDK pkgs run: go list ./... > pkgs.txt - name: Split pkgs into 4 files @@ -105,7 +105,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - uses: technote-space/get-diff-action@v6.0.1 with: PATTERNS: | @@ -201,7 +201,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - uses: technote-space/get-diff-action@v6.0.1 id: git_diff with: @@ -241,7 +241,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Display go version run: go version - uses: technote-space/get-diff-action@v6.0.1 diff --git a/Dockerfile b/Dockerfile index 026f222c594a..69718406a317 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,7 @@ # > docker run -it -p 26657:26657 -p 26656:26656 -v ~/.simappcli:/root/.simapp simapp simd keys add foo # > docker run -it -p 26657:26657 -p 26656:26656 -v ~/.simappcli:/root/.simapp simapp simd keys list # TODO: demo connecting rest-server (or is this in server now?) -FROM golang:1.18-alpine AS build-env +FROM golang:1.19-alpine AS build-env # Install minimum necessary dependencies ENV PACKAGES curl make git libc-dev bash gcc linux-headers eudev-dev python3 diff --git a/README.md b/README.md index c00ce7ee656c..02f12fd6173d 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ The Cosmos SDK is a framework for building blockchain applications. [Tendermint **WARNING**: The Cosmos SDK has mostly stabilized, but we are still making some breaking changes. -**Note**: Requires [Go 1.18+](https://go.dev/dl) +**Note**: Requires [Go 1.19+](https://go.dev/dl) ## Quick Start diff --git a/client/v2/go.mod b/client/v2/go.mod index d83f8b8ab04b..5abb33a15e60 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -1,6 +1,6 @@ module github.com/cosmos/cosmos-sdk/client/v2 -go 1.18 +go 1.19 require ( github.com/cosmos/cosmos-proto v1.0.0-alpha7 diff --git a/contrib/images/simd-dlv/Dockerfile b/contrib/images/simd-dlv/Dockerfile index e88fc4da0d9e..78807305e3a0 100644 --- a/contrib/images/simd-dlv/Dockerfile +++ b/contrib/images/simd-dlv/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.18-alpine AS build +FROM golang:1.19-alpine AS build RUN apk add build-base git linux-headers libc-dev RUN go install github.com/go-delve/delve/cmd/dlv@latest diff --git a/contrib/images/simd-env/Dockerfile b/contrib/images/simd-env/Dockerfile index 0d3565375837..aaeab8c5e5b7 100644 --- a/contrib/images/simd-env/Dockerfile +++ b/contrib/images/simd-env/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.18-alpine AS build +FROM golang:1.19-alpine AS build RUN apk add build-base git linux-headers diff --git a/contrib/rosetta/rosetta-ci/Dockerfile b/contrib/rosetta/rosetta-ci/Dockerfile index d4cfc58528e9..a333fdc01b73 100644 --- a/contrib/rosetta/rosetta-ci/Dockerfile +++ b/contrib/rosetta/rosetta-ci/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.18-alpine as build +FROM golang:1.19-alpine as build RUN apk add --no-cache tar git diff --git a/contrib/rosetta/rosetta-cli/Dockerfile b/contrib/rosetta/rosetta-cli/Dockerfile index da6ef2879239..f4fc15d9bced 100644 --- a/contrib/rosetta/rosetta-cli/Dockerfile +++ b/contrib/rosetta/rosetta-cli/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.18-alpine as build +FROM golang:1.19-alpine as build RUN apk add git gcc libc-dev --no-cache diff --git a/core/go.mod b/core/go.mod index 00cf457281e7..cbd97b677804 100644 --- a/core/go.mod +++ b/core/go.mod @@ -1,6 +1,6 @@ module cosmossdk.io/core -go 1.18 +go 1.19 require ( github.com/cosmos/cosmos-proto v1.0.0-alpha7 diff --git a/cosmovisor/go.mod b/cosmovisor/go.mod index 1c3f2595da7b..cb775b9b3c8d 100644 --- a/cosmovisor/go.mod +++ b/cosmovisor/go.mod @@ -1,6 +1,6 @@ module github.com/cosmos/cosmos-sdk/cosmovisor -go 1.18 +go 1.19 require ( github.com/cosmos/cosmos-sdk v0.46.1 diff --git a/errors/go.mod b/errors/go.mod index c798fa867709..0dff1ecbac92 100644 --- a/errors/go.mod +++ b/errors/go.mod @@ -1,6 +1,6 @@ module cosmossdk.io/errors -go 1.18 +go 1.19 require ( github.com/pkg/errors v0.9.1 diff --git a/go.mod b/go.mod index af7a597cccc2..7c915023cc67 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -go 1.18 +go 1.19 module github.com/cosmos/cosmos-sdk diff --git a/math/go.mod b/math/go.mod index ac1dfad9d0b3..abf46b07232e 100644 --- a/math/go.mod +++ b/math/go.mod @@ -1,6 +1,6 @@ module cosmossdk.io/math -go 1.18 +go 1.19 require github.com/stretchr/testify v1.7.0 diff --git a/orm/go.mod b/orm/go.mod index c619d400c0bb..bcc7c7e65801 100644 --- a/orm/go.mod +++ b/orm/go.mod @@ -1,6 +1,6 @@ module github.com/cosmos/cosmos-sdk/orm -go 1.18 +go 1.19 require ( cosmossdk.io/errors v1.0.0-beta.6 diff --git a/store/tools/ics23/go.mod b/store/tools/ics23/go.mod index efb8f435da0f..17107df35acb 100644 --- a/store/tools/ics23/go.mod +++ b/store/tools/ics23/go.mod @@ -1,6 +1,6 @@ module github.com/cosmos/cosmos-sdk/store/tools/ics23 -go 1.18 +go 1.19 require ( github.com/celestiaorg/smt v0.3.0 From 2ee350371eadcfad8a0b3c68723f776a8db39e9b Mon Sep 17 00:00:00 2001 From: mmsqe Date: Wed, 28 Sep 2022 02:16:13 +0800 Subject: [PATCH 6/8] fix: double close (#13400) --- baseapp/baseapp_test.go | 18 +++++++++--------- snapshots/helpers_test.go | 1 - snapshots/manager_test.go | 2 +- snapshots/stream.go | 4 ---- snapshots/types/format.go | 2 +- store/rootmulti/snapshot_test.go | 2 +- store/v2alpha1/multi/snapshot_test.go | 2 +- 7 files changed, 13 insertions(+), 18 deletions(-) diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index bf5d6b213e8d..5780720fc9ab 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -1792,7 +1792,7 @@ func TestSnapshotWithPruning(t *testing.T) { pruningOpts: pruningtypes.NewPruningOptions(pruningtypes.PruningNothing), }, expectedSnapshots: []*abci.Snapshot{ - {Height: 20, Format: 2, Chunks: 5}, + {Height: 20, Format: snapshottypes.CurrentFormat, Chunks: 5}, }, }, "prune everything with snapshot": { @@ -1804,7 +1804,7 @@ func TestSnapshotWithPruning(t *testing.T) { pruningOpts: pruningtypes.NewPruningOptions(pruningtypes.PruningEverything), }, expectedSnapshots: []*abci.Snapshot{ - {Height: 20, Format: 2, Chunks: 5}, + {Height: 20, Format: snapshottypes.CurrentFormat, Chunks: 5}, }, }, "default pruning with snapshot": { @@ -1816,7 +1816,7 @@ func TestSnapshotWithPruning(t *testing.T) { pruningOpts: pruningtypes.NewPruningOptions(pruningtypes.PruningDefault), }, expectedSnapshots: []*abci.Snapshot{ - {Height: 20, Format: 2, Chunks: 5}, + {Height: 20, Format: snapshottypes.CurrentFormat, Chunks: 5}, }, }, "custom": { @@ -1828,8 +1828,8 @@ func TestSnapshotWithPruning(t *testing.T) { pruningOpts: pruningtypes.NewCustomPruningOptions(12, 12), }, expectedSnapshots: []*abci.Snapshot{ - {Height: 25, Format: 2, Chunks: 6}, - {Height: 20, Format: 2, Chunks: 5}, + {Height: 25, Format: snapshottypes.CurrentFormat, Chunks: 6}, + {Height: 20, Format: snapshottypes.CurrentFormat, Chunks: 5}, }, }, "no snapshots": { @@ -1850,9 +1850,9 @@ func TestSnapshotWithPruning(t *testing.T) { pruningOpts: pruningtypes.NewPruningOptions(pruningtypes.PruningNothing), }, expectedSnapshots: []*abci.Snapshot{ - {Height: 9, Format: 2, Chunks: 2}, - {Height: 6, Format: 2, Chunks: 2}, - {Height: 3, Format: 2, Chunks: 1}, + {Height: 9, Format: snapshottypes.CurrentFormat, Chunks: 2}, + {Height: 6, Format: snapshottypes.CurrentFormat, Chunks: 2}, + {Height: 3, Format: snapshottypes.CurrentFormat, Chunks: 1}, }, }, } @@ -1928,7 +1928,7 @@ func TestLoadSnapshotChunk(t *testing.T) { }{ "Existing snapshot": {2, snapshottypes.CurrentFormat, 1, false}, "Missing height": {100, snapshottypes.CurrentFormat, 1, true}, - "Missing format": {2, 3, 1, true}, + "Missing format": {2, 4, 1, true}, "Missing chunk": {2, snapshottypes.CurrentFormat, 9, true}, "Zero height": {0, snapshottypes.CurrentFormat, 1, true}, "Zero format": {2, 0, 1, true}, diff --git a/snapshots/helpers_test.go b/snapshots/helpers_test.go index 24051a17a927..412b7de6caac 100644 --- a/snapshots/helpers_test.go +++ b/snapshots/helpers_test.go @@ -77,7 +77,6 @@ func snapshotItems(items [][]byte) [][]byte { _ = snapshottypes.WriteExtensionItem(protoWriter, item) } _ = protoWriter.Close() - _ = zWriter.Close() _ = bufWriter.Flush() _ = chunkWriter.Close() }() diff --git a/snapshots/manager_test.go b/snapshots/manager_test.go index 7fbddd6c7d6d..8f8e8d3da8d7 100644 --- a/snapshots/manager_test.go +++ b/snapshots/manager_test.go @@ -91,7 +91,7 @@ func TestManager_Take(t *testing.T) { Height: 5, Format: snapshotter.SnapshotFormat(), Chunks: 1, - Hash: []uint8{0xcd, 0x17, 0x9e, 0x7f, 0x28, 0xb6, 0x82, 0x90, 0xc7, 0x25, 0xf3, 0x42, 0xac, 0x65, 0x73, 0x50, 0xaa, 0xa0, 0x10, 0x5c, 0x40, 0x8c, 0xd5, 0x1, 0xed, 0x82, 0xb5, 0xca, 0x8b, 0xe0, 0x83, 0xa2}, + Hash: []uint8{0xcf, 0xd8, 0x16, 0xd2, 0xf8, 0x11, 0xe8, 0x90, 0x92, 0xf1, 0xfe, 0x3b, 0xea, 0xd2, 0x94, 0xfc, 0xfa, 0x4f, 0x9e, 0x2a, 0x91, 0xbe, 0xb0, 0x50, 0x83, 0xe9, 0x28, 0x62, 0x48, 0x6a, 0x4b, 0x4}, Metadata: types.Metadata{ ChunkHashes: checksums(expectChunks), }, diff --git a/snapshots/stream.go b/snapshots/stream.go index 935028313bb5..ce000f3e9c3d 100644 --- a/snapshots/stream.go +++ b/snapshots/stream.go @@ -57,10 +57,6 @@ func (sw *StreamWriter) Close() error { sw.chunkWriter.CloseWithError(err) return err } - if err := sw.zWriter.Close(); err != nil { - sw.chunkWriter.CloseWithError(err) - return err - } if err := sw.bufWriter.Flush(); err != nil { sw.chunkWriter.CloseWithError(err) return err diff --git a/snapshots/types/format.go b/snapshots/types/format.go index d5e960660ac9..317b6a6e329e 100644 --- a/snapshots/types/format.go +++ b/snapshots/types/format.go @@ -3,4 +3,4 @@ package types // CurrentFormat is the currently used format for snapshots. Snapshots using the same format // must be identical across all nodes for a given height, so this must be bumped when the binary // snapshot output changes. -const CurrentFormat uint32 = 2 +const CurrentFormat uint32 = 3 diff --git a/store/rootmulti/snapshot_test.go b/store/rootmulti/snapshot_test.go index bad1603da7c9..de7880788eee 100644 --- a/store/rootmulti/snapshot_test.go +++ b/store/rootmulti/snapshot_test.go @@ -128,7 +128,7 @@ func TestMultistoreSnapshot_Checksum(t *testing.T) { "aa048b4ee0f484965d7b3b06822cf0772cdcaad02f3b1b9055e69f2cb365ef3c", "7921eaa3ed4921341e504d9308a9877986a879fe216a099c86e8db66fcba4c63", "a4a864e6c02c9fca5837ec80dc84f650b25276ed7e4820cf7516ced9f9901b86", - "ca2879ac6e7205d257440131ba7e72bef784cd61642e32b847729e543c1928b9", + "980925390cc50f14998ecb1e87de719ca9dd7e72f5fefbe445397bf670f36c31", }}, } for _, tc := range testcases { diff --git a/store/v2alpha1/multi/snapshot_test.go b/store/v2alpha1/multi/snapshot_test.go index 77637910e768..c3d1a7baf82f 100644 --- a/store/v2alpha1/multi/snapshot_test.go +++ b/store/v2alpha1/multi/snapshot_test.go @@ -151,7 +151,7 @@ func TestMultistoreSnapshot_Checksum(t *testing.T) { "05dfef0e32c34ef3900300f9de51f228d7fb204fa8f4e4d0d1529f083d122029", "77d30aeeb427b0bdcedf3639adde1e822c15233d652782e171125280875aa492", "c00c3801da889ea4370f0e647ffe1e291bd47f500e2a7269611eb4cc198b993f", - "6d565eb28776631f3e3e764decd53436c3be073a8a01fa5434afd539f9ae6eda", + "df5b8eeea83ca7f1e10824d0161bff46200ca12c02f50c1f42c8ed156368493e", }}, } for _, tc := range testcases { From 6a9ec0392fcd92175e9c8baf85fe66429bfce929 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 14 Dec 2022 22:39:42 +0000 Subject: [PATCH 7/8] fix(store): Fix the TestFileStreamingService unit test. (backport #14305) (#14309) Co-authored-by: Daniel Wedul Co-authored-by: Julien Robert --- store/streaming/file/service_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/store/streaming/file/service_test.go b/store/streaming/file/service_test.go index 0acf4502de06..fbbb55090167 100644 --- a/store/streaming/file/service_test.go +++ b/store/streaming/file/service_test.go @@ -118,7 +118,8 @@ func TestFileStreamingService(t *testing.T) { defer os.RemoveAll(testDir) testKeys := []types.StoreKey{mockStoreKey1, mockStoreKey2} - testStreamingService, err := NewStreamingService(testDir, testPrefix, testKeys, testMarshaller, true, false, false) + var err error + testStreamingService, err = NewStreamingService(testDir, testPrefix, testKeys, testMarshaller, true, false, false) require.Nil(t, err) require.IsType(t, &StreamingService{}, testStreamingService) require.Equal(t, testPrefix, testStreamingService.filePrefix) From 8985cf8b87f0f5af277e1d5965bf2e73f36f3ddd Mon Sep 17 00:00:00 2001 From: yihuang Date: Thu, 18 Aug 2022 15:33:55 +0800 Subject: [PATCH 8/8] feat: Make extension snapshotter interface safer to use (#11825) * Make extension snapshotter interface safer to use Closes: #11824 Solution: - Use new methods `SnapshotExtension`/`RestoreExtension` to handle payload stream specifically. - Improve unit tests. * update changelog * Update snapshots/types/util.go * changelog * go linter * Update CHANGELOG.md Co-authored-by: Aleksandr Bezobchuk --- docs/architecture/adr-049-state-sync-hooks.md | 20 ++++- snapshots/helpers_test.go | 77 +++++++++++++++++-- snapshots/manager.go | 40 ++++++++-- snapshots/manager_test.go | 18 +++-- snapshots/types/snapshotter.go | 20 +++-- snapshots/types/util.go | 6 +- 6 files changed, 151 insertions(+), 30 deletions(-) diff --git a/docs/architecture/adr-049-state-sync-hooks.md b/docs/architecture/adr-049-state-sync-hooks.md index e1616c2265ba..5cc2b684c4df 100644 --- a/docs/architecture/adr-049-state-sync-hooks.md +++ b/docs/architecture/adr-049-state-sync-hooks.md @@ -3,10 +3,11 @@ ## Changelog - Jan 19, 2022: Initial Draft +- Apr 29, 2022: Safer extension snapshotter interface ## Status -Draft, Under Implementation +Implemented ## Abstract @@ -107,11 +108,16 @@ func (m *Manager) RegisterExtensions(extensions ...types.ExtensionSnapshotter) e On top of the existing `Snapshotter` interface for the `multistore`, we add `ExtensionSnapshotter` interface for the extension snapshotters. Three more function signatures: `SnapshotFormat()`, `SupportedFormats()` and `SnapshotName()` are added to `ExtensionSnapshotter`. ```go +// ExtensionPayloadReader read extension payloads, +// it returns io.EOF when reached either end of stream or the extension boundaries. +type ExtensionPayloadReader = func() ([]byte, error) + +// ExtensionPayloadWriter is a helper to write extension payloads to underlying stream. +type ExtensionPayloadWriter = func([]byte) error + // ExtensionSnapshotter is an extension Snapshotter that is appended to the snapshot stream. // ExtensionSnapshotter has an unique name and manages it's own internal formats. type ExtensionSnapshotter interface { - Snapshotter - // SnapshotName returns the name of snapshotter, it should be unique in the manager. SnapshotName() string @@ -120,6 +126,14 @@ type ExtensionSnapshotter interface { // SupportedFormats returns a list of formats it can restore from. SupportedFormats() []uint32 + + // SnapshotExtension writes extension payloads into the underlying protobuf stream. + SnapshotExtension(height uint64, payloadWriter ExtensionPayloadWriter) error + + // RestoreExtension restores an extension state snapshot, + // the payload reader returns `io.EOF` when reached the extension boundaries. + RestoreExtension(height uint64, format uint32, payloadReader ExtensionPayloadReader) error + } ``` diff --git a/snapshots/helpers_test.go b/snapshots/helpers_test.go index 412b7de6caac..6e2dc6d26bb9 100644 --- a/snapshots/helpers_test.go +++ b/snapshots/helpers_test.go @@ -18,6 +18,7 @@ import ( "github.com/cosmos/cosmos-sdk/snapshots" snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types" "github.com/cosmos/cosmos-sdk/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -62,7 +63,7 @@ func readChunks(chunks <-chan io.ReadCloser) [][]byte { } // snapshotItems serialize a array of bytes as SnapshotItem_ExtensionPayload, and return the chunks. -func snapshotItems(items [][]byte) [][]byte { +func snapshotItems(items [][]byte, ext snapshottypes.ExtensionSnapshotter) [][]byte { // copy the same parameters from the code snapshotChunkSize := uint64(10e6) snapshotBufferSize := int(snapshotChunkSize) @@ -74,8 +75,20 @@ func snapshotItems(items [][]byte) [][]byte { zWriter, _ := zlib.NewWriterLevel(bufWriter, 7) protoWriter := protoio.NewDelimitedWriter(zWriter) for _, item := range items { - _ = snapshottypes.WriteExtensionItem(protoWriter, item) + _ = snapshottypes.WriteExtensionPayload(protoWriter, item) } + // write extension metadata + _ = protoWriter.WriteMsg(&snapshottypes.SnapshotItem{ + Item: &snapshottypes.SnapshotItem_Extension{ + Extension: &snapshottypes.SnapshotExtensionMeta{ + Name: ext.SnapshotName(), + Format: ext.SnapshotFormat(), + }, + }, + }) + _ = ext.SnapshotExtension(0, func(payload []byte) error { + return snapshottypes.WriteExtensionPayload(protoWriter, payload) + }) _ = protoWriter.Close() _ = bufWriter.Flush() _ = chunkWriter.Close() @@ -109,10 +122,11 @@ func (m *mockSnapshotter) Restore( return snapshottypes.SnapshotItem{}, errors.New("already has contents") } + var item snapshottypes.SnapshotItem m.items = [][]byte{} for { - item := &snapshottypes.SnapshotItem{} - err := protoReader.ReadMsg(item) + item.Reset() + err := protoReader.ReadMsg(&item) if err == io.EOF { break } else if err != nil { @@ -120,17 +134,17 @@ func (m *mockSnapshotter) Restore( } payload := item.GetExtensionPayload() if payload == nil { - return snapshottypes.SnapshotItem{}, sdkerrors.Wrap(err, "invalid protobuf message") + break } m.items = append(m.items, payload.Payload) } - return snapshottypes.SnapshotItem{}, nil + return item, nil } func (m *mockSnapshotter) Snapshot(height uint64, protoWriter protoio.Writer) error { for _, item := range m.items { - if err := snapshottypes.WriteExtensionItem(protoWriter, item); err != nil { + if err := snapshottypes.WriteExtensionPayload(protoWriter, item); err != nil { return err } } @@ -215,3 +229,52 @@ func (m *hungSnapshotter) Restore( ) (snapshottypes.SnapshotItem, error) { panic("not implemented") } + +type extSnapshotter struct { + state []uint64 +} + +func newExtSnapshotter(count int) *extSnapshotter { + state := make([]uint64, 0, count) + for i := 0; i < count; i++ { + state = append(state, uint64(i)) + } + return &extSnapshotter{ + state, + } +} + +func (s *extSnapshotter) SnapshotName() string { + return "mock" +} + +func (s *extSnapshotter) SnapshotFormat() uint32 { + return 1 +} + +func (s *extSnapshotter) SupportedFormats() []uint32 { + return []uint32{1} +} + +func (s *extSnapshotter) SnapshotExtension(height uint64, payloadWriter snapshottypes.ExtensionPayloadWriter) error { + for _, i := range s.state { + if err := payloadWriter(sdk.Uint64ToBigEndian(uint64(i))); err != nil { + return err + } + } + return nil +} + +func (s *extSnapshotter) RestoreExtension(height uint64, format uint32, payloadReader snapshottypes.ExtensionPayloadReader) error { + for { + payload, err := payloadReader() + if err == io.EOF { + break + } else if err != nil { + return err + } + s.state = append(s.state, sdk.BigEndianToUint64(payload)) + } + // finalize restoration + return nil +} diff --git a/snapshots/manager.go b/snapshots/manager.go index 05cbad3f5b30..efc123e9e498 100644 --- a/snapshots/manager.go +++ b/snapshots/manager.go @@ -84,6 +84,9 @@ func NewManager(store *Store, opts types.SnapshotOptions, multistore types.Snaps // RegisterExtensions register extension snapshotters to manager func (m *Manager) RegisterExtensions(extensions ...types.ExtensionSnapshotter) error { + if m.extensions == nil { + m.extensions = make(map[string]types.ExtensionSnapshotter, len(extensions)) + } for _, extension := range extensions { name := extension.SnapshotName() if _, ok := m.extensions[name]; ok { @@ -215,7 +218,10 @@ func (m *Manager) createSnapshot(height uint64, ch chan<- io.ReadCloser) { streamWriter.CloseWithError(err) return } - if err := extension.Snapshot(height, streamWriter); err != nil { + payloadWriter := func(payload []byte) error { + return types.WriteExtensionPayload(streamWriter, payload) + } + if err := extension.SnapshotExtension(height, payloadWriter); err != nil { streamWriter.CloseWithError(err) return } @@ -305,24 +311,40 @@ func (m *Manager) Restore(snapshot types.Snapshot) error { // restoreSnapshot do the heavy work of snapshot restoration after preliminary checks on request have passed. func (m *Manager) restoreSnapshot(snapshot types.Snapshot, chChunks <-chan io.ReadCloser) error { + var nextItem types.SnapshotItem + streamReader, err := NewStreamReader(chChunks) if err != nil { return err } defer streamReader.Close() - next, err := m.multistore.Restore(snapshot.Height, snapshot.Format, streamReader) + // payloadReader reads an extension payload for extension snapshotter, it returns `io.EOF` at extension boundaries. + payloadReader := func() ([]byte, error) { + nextItem.Reset() + if err := streamReader.ReadMsg(&nextItem); err != nil { + return nil, err + } + payload := nextItem.GetExtensionPayload() + if payload == nil { + return nil, io.EOF + } + return payload.Payload, nil + } + + nextItem, err = m.multistore.Restore(snapshot.Height, snapshot.Format, streamReader) if err != nil { return sdkerrors.Wrap(err, "multistore restore") } + for { - if next.Item == nil { + if nextItem.Item == nil { // end of stream break } - metadata := next.GetExtension() + metadata := nextItem.GetExtension() if metadata == nil { - return sdkerrors.Wrapf(sdkerrors.ErrLogic, "unknown snapshot item %T", next.Item) + return sdkerrors.Wrapf(sdkerrors.ErrLogic, "unknown snapshot item %T", nextItem.Item) } extension, ok := m.extensions[metadata.Name] if !ok { @@ -331,10 +353,14 @@ func (m *Manager) restoreSnapshot(snapshot types.Snapshot, chChunks <-chan io.Re if !IsFormatSupported(extension, metadata.Format) { return sdkerrors.Wrapf(types.ErrUnknownFormat, "format %v for extension %s", metadata.Format, metadata.Name) } - next, err = extension.Restore(snapshot.Height, metadata.Format, streamReader) - if err != nil { + + if err := extension.RestoreExtension(snapshot.Height, metadata.Format, payloadReader); err != nil { return sdkerrors.Wrapf(err, "extension %s restore", metadata.Name) } + + if nextItem.GetExtensionPayload() != nil { + return sdkerrors.Wrapf(err, "extension %s don't exhausted payload stream", metadata.Name) + } } return nil } diff --git a/snapshots/manager_test.go b/snapshots/manager_test.go index 8f8e8d3da8d7..ee4c3b471189 100644 --- a/snapshots/manager_test.go +++ b/snapshots/manager_test.go @@ -68,11 +68,15 @@ func TestManager_Take(t *testing.T) { items: items, prunedHeights: make(map[int64]struct{}), } - expectChunks := snapshotItems(items) + extSnapshotter := newExtSnapshotter(10) + + expectChunks := snapshotItems(items, extSnapshotter) manager := snapshots.NewManager(store, opts, snapshotter, nil, log.NewNopLogger()) + err := manager.RegisterExtensions(extSnapshotter) + require.NoError(t, err) // nil manager should return error - _, err := (*snapshots.Manager)(nil).Create(1) + _, err = (*snapshots.Manager)(nil).Create(1) require.Error(t, err) // creating a snapshot at a lower height than the latest should error @@ -91,7 +95,7 @@ func TestManager_Take(t *testing.T) { Height: 5, Format: snapshotter.SnapshotFormat(), Chunks: 1, - Hash: []uint8{0xcf, 0xd8, 0x16, 0xd2, 0xf8, 0x11, 0xe8, 0x90, 0x92, 0xf1, 0xfe, 0x3b, 0xea, 0xd2, 0x94, 0xfc, 0xfa, 0x4f, 0x9e, 0x2a, 0x91, 0xbe, 0xb0, 0x50, 0x83, 0xe9, 0x28, 0x62, 0x48, 0x6a, 0x4b, 0x4}, + Hash: []uint8{0xc5, 0xf7, 0xfe, 0xea, 0xd3, 0x4d, 0x3e, 0x87, 0xff, 0x41, 0xa2, 0x27, 0xfa, 0xcb, 0x38, 0x17, 0xa, 0x5, 0xeb, 0x27, 0x4e, 0x16, 0x5e, 0xf3, 0xb2, 0x8b, 0x47, 0xd1, 0xe6, 0x94, 0x7e, 0x8b}, Metadata: types.Metadata{ ChunkHashes: checksums(expectChunks), }, @@ -133,7 +137,10 @@ func TestManager_Restore(t *testing.T) { target := &mockSnapshotter{ prunedHeights: make(map[int64]struct{}), } + extSnapshotter := newExtSnapshotter(0) manager := snapshots.NewManager(store, opts, target, nil, log.NewNopLogger()) + err := manager.RegisterExtensions(extSnapshotter) + require.NoError(t, err) expectItems := [][]byte{ {1, 2, 3}, @@ -141,10 +148,10 @@ func TestManager_Restore(t *testing.T) { {7, 8, 9}, } - chunks := snapshotItems(expectItems) + chunks := snapshotItems(expectItems, newExtSnapshotter(10)) // Restore errors on invalid format - err := manager.Restore(types.Snapshot{ + err = manager.Restore(types.Snapshot{ Height: 3, Format: 0, Hash: []byte{1, 2, 3}, @@ -204,6 +211,7 @@ func TestManager_Restore(t *testing.T) { } assert.Equal(t, expectItems, target.items) + assert.Equal(t, 10, len(extSnapshotter.state)) // Starting a new restore should fail now, because the target already has contents. err = manager.Restore(types.Snapshot{ diff --git a/snapshots/types/snapshotter.go b/snapshots/types/snapshotter.go index 76f800484a49..1641042a6233 100644 --- a/snapshots/types/snapshotter.go +++ b/snapshots/types/snapshotter.go @@ -22,17 +22,20 @@ type Snapshotter interface { // to determine which heights to retain until after the snapshot is complete. SetSnapshotInterval(snapshotInterval uint64) - // Restore restores a state snapshot, taking snapshot chunk readers as input. - // If the ready channel is non-nil, it returns a ready signal (by being closed) once the - // restorer is ready to accept chunks. + // Restore restores a state snapshot, taking the reader of protobuf message stream as input. Restore(height uint64, format uint32, protoReader protoio.Reader) (SnapshotItem, error) } +// ExtensionPayloadReader read extension payloads, +// it returns io.EOF when reached either end of stream or the extension boundaries. +type ExtensionPayloadReader = func() ([]byte, error) + +// ExtensionPayloadWriter is a helper to write extension payloads to underlying stream. +type ExtensionPayloadWriter = func([]byte) error + // ExtensionSnapshotter is an extension Snapshotter that is appended to the snapshot stream. // ExtensionSnapshotter has an unique name and manages it's own internal formats. type ExtensionSnapshotter interface { - Snapshotter - // SnapshotName returns the name of snapshotter, it should be unique in the manager. SnapshotName() string @@ -43,4 +46,11 @@ type ExtensionSnapshotter interface { // SupportedFormats returns a list of formats it can restore from. SupportedFormats() []uint32 + + // SnapshotExtension writes extension payloads into the underlying protobuf stream. + SnapshotExtension(height uint64, payloadWriter ExtensionPayloadWriter) error + + // RestoreExtension restores an extension state snapshot, + // the payload reader returns `io.EOF` when reached the extension boundaries. + RestoreExtension(height uint64, format uint32, payloadReader ExtensionPayloadReader) error } diff --git a/snapshots/types/util.go b/snapshots/types/util.go index 348b5057682d..e2d4949bf5c2 100644 --- a/snapshots/types/util.go +++ b/snapshots/types/util.go @@ -4,12 +4,12 @@ import ( protoio "github.com/gogo/protobuf/io" ) -// WriteExtensionItem writes an item payload for current extension snapshotter. -func WriteExtensionItem(protoWriter protoio.Writer, item []byte) error { +// WriteExtensionPayload writes an extension payload for current extension snapshotter. +func WriteExtensionPayload(protoWriter protoio.Writer, payload []byte) error { return protoWriter.WriteMsg(&SnapshotItem{ Item: &SnapshotItem_ExtensionPayload{ ExtensionPayload: &SnapshotExtensionPayload{ - Payload: item, + Payload: payload, }, }, })