Skip to content

Commit

Permalink
refactor(codec)!: update codec to x/tx v0.6.0 (cosmos#15873)
Browse files Browse the repository at this point in the history
Co-authored-by: Matt Kocubinski <[email protected]>
  • Loading branch information
2 people authored and rllola committed May 11, 2023
1 parent 1b3af21 commit 1dd011b
Show file tree
Hide file tree
Showing 36 changed files with 404 additions and 331 deletions.
10 changes: 4 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (crypto) [#15070](https://github.com/cosmos/cosmos-sdk/pull/15070) `GenerateFromPassword` and `Cost` from `bcrypt.go` now take a `uint32` instead of a `int` type.
* (x/capability) [#15344](https://github.com/cosmos/cosmos-sdk/pull/15344) Capability module was removed and is now housed in [IBC-GO](https://github.com/cosmos/ibc-go).
* [#15299](https://github.com/cosmos/cosmos-sdk/pull/15299) remove `StdTx` transaction and signing APIs. No SDK version has actually supported `StdTx` since before Stargate.
* (codec) [#15600](https://github.com/cosmos/cosmos-sdk/pull/15600) add support for getting signers to `codec.Codec` and protoregistry support to `InterfaceRegistry`:
* `Codec` is now a private interface and has the methods `InterfaceRegistry`, `GetMsgAnySigners`, `GetMsgV1Signers`, and `GetMsgV2Signers` which will fail when using `AminoCodec`.
All implementations of `Codec` by other users must now embed an official implementation from the `codec` package.
* `InterfaceRegistry` is now a private interface and implements `protodesc.Resolver` plus the `RangeFiles` method
All implementations of `InterfaceRegistry` by other users must now embed the official implementation.
* `AminoCodec` is marked as deprecated.
* (codec) [#15600](https://github.com/cosmos/cosmos-sdk/pull/15600) [#15873](https://github.com/cosmos/cosmos-sdk/pull/15873) add support for getting signers to `codec.Codec` and `InterfaceRegistry`:
* `Codec` has new methods `InterfaceRegistry`, `GetMsgAnySigners`, `GetMsgV1Signers`, and `GetMsgV2Signers` as well as unexported methods. All implementations of `Codec` by other users must now embed an official implementation from the `codec` package.
* `InterfaceRegistry` is has unexported methods and implements `protodesc.Resolver` plus the `RangeFiles` and `SigningContext` methods. All implementations of `InterfaceRegistry` by other users must now embed the official implementation.
* `AminoCodec` is marked as deprecated and no longer implements `Codec.
* (x/crisis) [#15852](https://github.com/cosmos/cosmos-sdk/pull/15852) Crisis keeper now takes a instance of the address codec to be able to decode user addresses
* (x/slashing) [#15875](https://github.com/cosmos/cosmos-sdk/pull/15875) `x/slashing.NewAppModule` now requires an `InterfaceRegistry` parameter.
* (client) [#15822](https://github.com/cosmos/cosmos-sdk/pull/15822) The return type of the interface method `TxConfig.SignModeHandler` has been changed to `x/tx/signing.HandlerMap`.
Expand Down
28 changes: 4 additions & 24 deletions codec/amino_codec.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
package codec

import (
"fmt"

"github.com/cosmos/gogoproto/proto"
protov2 "google.golang.org/protobuf/proto"

"github.com/cosmos/cosmos-sdk/codec/types"
)

// Deprecated: AminoCodec defines a codec that utilizes Codec for both binary and JSON
Expand All @@ -16,7 +11,10 @@ type AminoCodec struct {
*LegacyAmino
}

var _ Codec = &AminoCodec{}
var (
_ BinaryCodec = &AminoCodec{}
_ JSONCodec = &AminoCodec{}
)

// Deprecated: NewAminoCodec returns a reference to a new AminoCodec.
// Use NewLegacyAmino instead.
Expand Down Expand Up @@ -131,21 +129,3 @@ func (ac *AminoCodec) MarshalInterfaceJSON(i proto.Message) ([]byte, error) {
func (ac *AminoCodec) UnmarshalInterfaceJSON(bz []byte, ptr interface{}) error {
return ac.LegacyAmino.UnmarshalJSON(bz, ptr)
}

func (ac *AminoCodec) GetMsgAnySigners(*types.Any) ([]string, protov2.Message, error) {
return nil, nil, fmt.Errorf("amino codec does not support getting msg signers")
}

func (ac *AminoCodec) GetMsgV1Signers(proto.Message) ([]string, protov2.Message, error) {
return nil, nil, fmt.Errorf("amino codec does not support getting msg signers")
}

func (ac *AminoCodec) GetMsgV2Signers(protov2.Message) ([]string, error) {
return nil, fmt.Errorf("amino codec does not support getting msg signers")
}

func (ac *AminoCodec) InterfaceRegistry() types.InterfaceRegistry {
panic("amino codec does not support interface registry")
}

func (ac *AminoCodec) mustEmbedCodec() {}
6 changes: 3 additions & 3 deletions codec/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ type (
// GetMsgAnySigners returns the signers of the given message encoded in a protobuf Any
// as well as the decoded google.golang.org/protobuf/proto.Message that was used to
// extract the signers so that this can be used in other contexts.
GetMsgAnySigners(msg *types.Any) ([]string, protov2.Message, error)
GetMsgAnySigners(msg *types.Any) ([][]byte, protov2.Message, error)

// GetMsgV2Signers returns the signers of the given message.
GetMsgV2Signers(msg protov2.Message) ([]string, error)
GetMsgV2Signers(msg protov2.Message) ([][]byte, error)

// GetMsgV1Signers returns the signers of the given message plus the
// decoded google.golang.org/protobuf/proto.Message that was used to extract the
// signers so that this can be used in other contexts.
GetMsgV1Signers(msg proto.Message) ([]string, protov2.Message, error)
GetMsgV1Signers(msg proto.Message) ([][]byte, protov2.Message, error)

// mustEmbedCodec requires that all implementations of Codec embed an official implementation from the codec
// package. This allows new methods to be added to the Codec interface without breaking backwards compatibility.
Expand Down
6 changes: 5 additions & 1 deletion codec/codec_common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ func testMarshalingTestCase(require *require.Assertions, tc testCase, m mustMars
}
}

func testMarshaling(t *testing.T, cdc codec.Codec) {
func testMarshaling(t *testing.T, cdc interface {
codec.BinaryCodec
codec.JSONCodec
},
) {
any, err := types.NewAnyWithValue(&testdata.Dog{Name: "rufus"})
require.NoError(t, err)

Expand Down
23 changes: 6 additions & 17 deletions codec/proto_codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import (
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"

"cosmossdk.io/x/tx/signing"

"github.com/cosmos/cosmos-sdk/codec/types"
)

Expand All @@ -29,7 +27,6 @@ type ProtoCodecMarshaler interface {
// encoding.
type ProtoCodec struct {
interfaceRegistry types.InterfaceRegistry
getSignersCtx *signing.GetSignersContext
}

var (
Expand All @@ -39,16 +36,8 @@ var (

// NewProtoCodec returns a reference to a new ProtoCodec
func NewProtoCodec(interfaceRegistry types.InterfaceRegistry) *ProtoCodec {
getSignersCtx, err := signing.NewGetSignersContext(
signing.GetSignersOptions{
ProtoFiles: interfaceRegistry,
})
if err != nil {
panic(err)
}
return &ProtoCodec{
interfaceRegistry: interfaceRegistry,
getSignersCtx: getSignersCtx,
}
}

Expand Down Expand Up @@ -277,7 +266,7 @@ func (pc *ProtoCodec) InterfaceRegistry() types.InterfaceRegistry {
return pc.interfaceRegistry
}

func (pc ProtoCodec) GetMsgAnySigners(msg *types.Any) ([]string, proto.Message, error) {
func (pc ProtoCodec) GetMsgAnySigners(msg *types.Any) ([][]byte, proto.Message, error) {
msgv2, err := anyutil.Unpack(&anypb.Any{
TypeUrl: msg.TypeUrl,
Value: msg.Value,
Expand All @@ -286,17 +275,17 @@ func (pc ProtoCodec) GetMsgAnySigners(msg *types.Any) ([]string, proto.Message,
return nil, nil, err
}

signers, err := pc.getSignersCtx.GetSigners(msgv2)
signers, err := pc.interfaceRegistry.SigningContext().GetSigners(msgv2)
return signers, msgv2, err
}

func (pc *ProtoCodec) GetMsgV2Signers(msg proto.Message) ([]string, error) {
return pc.getSignersCtx.GetSigners(msg)
func (pc *ProtoCodec) GetMsgV2Signers(msg proto.Message) ([][]byte, error) {
return pc.interfaceRegistry.SigningContext().GetSigners(msg)
}

func (pc *ProtoCodec) GetMsgV1Signers(msg gogoproto.Message) ([]string, proto.Message, error) {
func (pc *ProtoCodec) GetMsgV1Signers(msg gogoproto.Message) ([][]byte, proto.Message, error) {
if msgV2, ok := msg.(proto.Message); ok {
signers, err := pc.getSignersCtx.GetSigners(msgV2)
signers, err := pc.interfaceRegistry.SigningContext().GetSigners(msgV2)
return signers, msgV2, err
}
a, err := types.NewAnyWithValue(msg)
Expand Down
28 changes: 22 additions & 6 deletions codec/proto_codec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"google.golang.org/grpc/encoding"
"google.golang.org/grpc/status"
protov2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoregistry"

"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
Expand Down Expand Up @@ -174,11 +175,16 @@ func BenchmarkProtoCodecMarshalLengthPrefixed(b *testing.B) {
}

func TestGetSigners(t *testing.T) {
interfaceRegistry := types.NewInterfaceRegistry()
interfaceRegistry, err := types.NewInterfaceRegistryWithOptions(types.InterfaceRegistryOptions{
AddressCodec: testAddressCodec{},
ValidatorAddressCodec: testAddressCodec{},
ProtoFiles: protoregistry.GlobalFiles,
})
require.NoError(t, err)
cdc := codec.NewProtoCodec(interfaceRegistry)
testAddr := sdk.AccAddress([]byte("test"))
testAddr := sdk.AccAddress("test")
testAddrStr := testAddr.String()
testAddr2 := sdk.AccAddress([]byte("test2"))
testAddr2 := sdk.AccAddress("test2")
testAddrStr2 := testAddr2.String()

msgSendV1 := banktypes.NewMsgSend(testAddr, testAddr2, sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(1))))
Expand All @@ -190,17 +196,27 @@ func TestGetSigners(t *testing.T) {

signers, msgSendV2Copy, err := cdc.GetMsgV1Signers(msgSendV1)
require.NoError(t, err)
require.Equal(t, []string{testAddrStr}, signers)
require.Equal(t, [][]byte{testAddr}, signers)
require.True(t, protov2.Equal(msgSendV2, msgSendV2Copy))

signers, err = cdc.GetMsgV2Signers(msgSendV2)
require.NoError(t, err)
require.Equal(t, []string{testAddrStr}, signers)
require.Equal(t, [][]byte{testAddr}, signers)

msgSendAny, err := types.NewAnyWithValue(msgSendV1)
require.NoError(t, err)
signers, msgSendV2Copy, err = cdc.GetMsgAnySigners(msgSendAny)
require.NoError(t, err)
require.Equal(t, []string{testAddrStr}, signers)
require.Equal(t, [][]byte{testAddr}, signers)
require.True(t, protov2.Equal(msgSendV2, msgSendV2Copy))
}

type testAddressCodec struct{}

func (t testAddressCodec) StringToBytes(text string) ([]byte, error) {
return sdk.AccAddressFromBech32(text)
}

func (t testAddressCodec) BytesToString(bz []byte) (string, error) {
return sdk.AccAddress(bz).String(), nil
}
64 changes: 58 additions & 6 deletions codec/types/interface_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import (
"google.golang.org/protobuf/reflect/protodesc"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"

"cosmossdk.io/core/address"

"cosmossdk.io/x/tx/signing"
)

// AnyUnpacker is an interface which allows safely unpacking types packed
Expand Down Expand Up @@ -65,6 +69,8 @@ type InterfaceRegistry interface {
// the entire FileDescriptorSet.
RangeFiles(f func(protoreflect.FileDescriptor) bool)

SigningContext() *signing.Context

// mustEmbedInterfaceRegistry requires that all implementations of InterfaceRegistry embed an official implementation
// from this package. This allows new methods to be added to the InterfaceRegistry interface without breaking
// backwards compatibility.
Expand Down Expand Up @@ -101,28 +107,60 @@ type interfaceRegistry struct {
interfaceImpls map[reflect.Type]interfaceMap
implInterfaces map[reflect.Type]reflect.Type
typeURLMap map[string]reflect.Type
signingCtx *signing.Context
}

type interfaceMap = map[string]reflect.Type

// NewInterfaceRegistry returns a new InterfaceRegistry
func NewInterfaceRegistry() InterfaceRegistry {
protoFiles, err := proto.MergedRegistry()
registry, err := NewInterfaceRegistryWithOptions(InterfaceRegistryOptions{
ProtoFiles: protoregistry.GlobalFiles,
AddressCodec: failingAddressCodec{},
ValidatorAddressCodec: failingAddressCodec{},
})
if err != nil {
panic(err)
}
return NewInterfaceRegistryWithProtoFiles(protoFiles)
return registry
}

// InterfaceRegistryOptions are options for creating a new InterfaceRegistry.
type InterfaceRegistryOptions struct {
// ProtoFiles is the set of files to use for the registry. It is required.
ProtoFiles *protoregistry.Files

// AddressCodec is the address codec to use for the registry. It is required.
AddressCodec address.Codec

// ValidatorAddressCodec is the validator address codec to use for the registry. It is required.
ValidatorAddressCodec address.Codec
}

// NewInterfaceRegistryWithProtoFiles returns a new InterfaceRegistry with the specified *protoregistry.Files instance.
func NewInterfaceRegistryWithProtoFiles(files *protoregistry.Files) InterfaceRegistry {
// NewInterfaceRegistryWithOptions returns a new InterfaceRegistry with the given options.
func NewInterfaceRegistryWithOptions(options InterfaceRegistryOptions) (InterfaceRegistry, error) {
if options.ProtoFiles == nil {
return nil, fmt.Errorf("proto files must be provided")
}

signingCtx, err := signing.NewContext(signing.Options{
FileResolver: options.ProtoFiles,
TypeResolver: nil,
AddressCodec: options.AddressCodec,
ValidatorAddressCodec: options.ValidatorAddressCodec,
})
if err != nil {
return nil, err
}

return &interfaceRegistry{
interfaceNames: map[string]reflect.Type{},
interfaceImpls: map[reflect.Type]interfaceMap{},
implInterfaces: map[reflect.Type]reflect.Type{},
typeURLMap: map[string]reflect.Type{},
Files: files,
}
Files: options.ProtoFiles,
signingCtx: signingCtx,
}, nil
}

func (registry *interfaceRegistry) RegisterInterface(protoName string, iface interface{}, impls ...proto.Message) {
Expand Down Expand Up @@ -314,6 +352,10 @@ func (registry *interfaceRegistry) Resolve(typeURL string) (proto.Message, error
return msg, nil
}

func (registry *interfaceRegistry) SigningContext() *signing.Context {
return registry.signingCtx
}

func (registry *interfaceRegistry) mustEmbedInterfaceRegistry() {}

// UnpackInterfaces is a convenience function that calls UnpackInterfaces
Expand All @@ -324,3 +366,13 @@ func UnpackInterfaces(x interface{}, unpacker AnyUnpacker) error {
}
return nil
}

type failingAddressCodec struct{}

func (f failingAddressCodec) StringToBytes(string) ([]byte, error) {
return nil, fmt.Errorf("InterfaceRegistry requires a proper address codec implementation to do address conversion")
}

func (f failingAddressCodec) BytesToString([]byte) (string, error) {
return "", fmt.Errorf("InterfaceRegistry requires a proper address codec implementation to do address conversion")
}
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require (
cosmossdk.io/log v1.1.0
cosmossdk.io/math v1.0.0
cosmossdk.io/store v0.1.0-alpha.1.0.20230328185921-37ba88872dbc
cosmossdk.io/x/tx v0.5.5
cosmossdk.io/x/tx v0.6.1
github.com/99designs/keyring v1.2.1
github.com/armon/go-metrics v0.4.1
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816
Expand Down Expand Up @@ -162,6 +162,8 @@ require (

// Below are the long-lived replace of the Cosmos SDK
replace (
// TODO: remove after release 0.6.2
cosmossdk.io/x/tx => ./x/tx
// use cosmos fork of keyring
github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0
// dgrijalva/jwt-go is deprecated and doesn't receive security updates.
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ cosmossdk.io/math v1.0.0 h1:ro9w7eKx23om2tZz/VM2Pf+z2WAbGX1yDQQOJ6iGeJw=
cosmossdk.io/math v1.0.0/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k=
cosmossdk.io/store v0.1.0-alpha.1.0.20230328185921-37ba88872dbc h1:9piuA+NYmhe+SyMPtMoboLw/djgDbrI3dD5TG020Tnk=
cosmossdk.io/store v0.1.0-alpha.1.0.20230328185921-37ba88872dbc/go.mod h1:UFF5rmjN7WYVfxo6ArdY/l1+yyWMURBWOmSJypGqFHQ=
cosmossdk.io/x/tx v0.5.5 h1:9XG3KOrqObt7Rw7KhT7fiqRd6EepUfmA9ERa8CHj1WM=
cosmossdk.io/x/tx v0.5.5/go.mod h1:Oh3Kh+IPOfMEILNxVd2e8SLqRrIjYHpdGBfDg4ghU/k=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
Expand Down
Loading

0 comments on commit 1dd011b

Please sign in to comment.