refactor(codec)!: update codec to x/tx v0.6.0 (#15873)

Co-authored-by: Matt Kocubinski <mkocubinski@gmail.com>
This commit is contained in:
Aaron Craelius 2023-04-28 04:13:28 -04:00 committed by GitHub
parent 3936030e16
commit cb1641c1b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 409 additions and 336 deletions

View File

@ -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`.

View File

@ -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
@ -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.
@ -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() {}

View File

@ -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.

View File

@ -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)

View File

@ -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"
)
@ -29,7 +27,6 @@ type ProtoCodecMarshaler interface {
// encoding.
type ProtoCodec struct {
interfaceRegistry types.InterfaceRegistry
getSignersCtx *signing.GetSignersContext
}
var (
@ -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,
}
}
@ -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,
@ -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)

View File

@ -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"
@ -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))))
@ -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
}

View File

@ -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
@ -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.
@ -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
}
// NewInterfaceRegistryWithProtoFiles returns a new InterfaceRegistry with the specified *protoregistry.Files instance.
func NewInterfaceRegistryWithProtoFiles(files *protoregistry.Files) InterfaceRegistry {
// 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
}
// 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) {
@ -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
@ -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
go.mod
View File

@ -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
@ -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.

2
go.sum
View File

@ -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=

View File

@ -24,6 +24,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/std"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/types/msgservice"
)
@ -97,7 +98,22 @@ func ProvideApp() (
_, _ = fmt.Fprintln(os.Stderr, err.Error())
}
interfaceRegistry := codectypes.NewInterfaceRegistryWithProtoFiles(protoFiles)
interfaceRegistry, err := codectypes.NewInterfaceRegistryWithOptions(codectypes.InterfaceRegistryOptions{
ProtoFiles: protoFiles,
AddressCodec: globalAccAddressCodec{},
ValidatorAddressCodec: globalValAddressCodec{},
})
if err != nil {
return nil, nil, nil, nil, nil, nil, nil, nil, nil, err
}
// validate the signing context to make sure that messages are properly configured
// with cosmos.msg.v1.signer
err = interfaceRegistry.SigningContext().Validate()
if err != nil {
return nil, nil, nil, nil, nil, nil, nil, nil, nil, err
}
amino := codec.NewLegacyAmino()
std.RegisterInterfaces(interfaceRegistry)
@ -212,3 +228,33 @@ func ProvideTransientStoreService(key depinject.ModuleKey, app *AppBuilder) stor
func ProvideEventService() event.Service {
return EventService{}
}
// globalAccAddressCodec is a temporary address codec that we will use until we
// can populate it with the correct bech32 prefixes without depending on the global.
type globalAccAddressCodec struct{}
func (g globalAccAddressCodec) StringToBytes(text string) ([]byte, error) {
if text == "" {
return nil, nil
}
return sdk.AccAddressFromBech32(text)
}
func (g globalAccAddressCodec) BytesToString(bz []byte) (string, error) {
if bz == nil {
return "", nil
}
return sdk.AccAddress(bz).String(), nil
}
// globalValAddressCodec is a temporary address codec that we will use until we
// can populate it with the correct bech32 prefixes without depending on the global.
type globalValAddressCodec struct{}
func (g globalValAddressCodec) StringToBytes(text string) ([]byte, error) {
return sdk.ValAddressFromBech32(text)
}
func (g globalValAddressCodec) BytesToString(bz []byte) (string, error) {
return sdk.ValAddress(bz).String(), nil
}

View File

@ -14,6 +14,8 @@ import (
"cosmossdk.io/client/v2/autocli"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/log"
authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec"
abci "github.com/cometbft/cometbft/abci/types"
dbm "github.com/cosmos/cosmos-db"
"github.com/cosmos/gogoproto/proto"
@ -40,7 +42,6 @@ import (
"github.com/cosmos/cosmos-sdk/client/grpc/cmtservice"
nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/address"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/runtime"
runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services"
@ -625,7 +626,10 @@ func (app *SimApp) AutoCliOpts() autocli.AppOptions {
}
}
return autocli.AppOptions{Modules: modules, AddressCodec: address.NewBech32Codec(sdk.Bech32MainPrefix)}
return autocli.AppOptions{
Modules: modules,
AddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()),
}
}
// DefaultGenesis returns a default genesis from the registered AppModuleBasic's.

View File

@ -5,9 +5,10 @@ import (
"fmt"
"log"
storetypes "cosmossdk.io/store/types"
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
storetypes "cosmossdk.io/store/types"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
sdk "github.com/cosmos/cosmos-sdk/types"
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"

View File

@ -38,7 +38,7 @@ require (
cloud.google.com/go/storage v1.30.0 // indirect
cosmossdk.io/collections v0.1.0 // indirect
cosmossdk.io/errors v1.0.0-beta.7 // indirect
cosmossdk.io/x/tx v0.5.5 // indirect
cosmossdk.io/x/tx v0.6.1 // indirect
filippo.io/edwards25519 v1.0.0 // indirect
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/99designs/keyring v1.2.1 // indirect
@ -205,6 +205,8 @@ replace (
cosmossdk.io/x/feegrant => ../x/feegrant
cosmossdk.io/x/nft => ../x/nft
cosmossdk.io/x/upgrade => ../x/upgrade
// TODO: remove after release 0.6.2
cosmossdk.io/x/tx => ../x/tx
)
// Below are the long-lived replace of the SimApp

View File

@ -200,8 +200,8 @@ cosmossdk.io/log v1.1.0 h1:v0ogPHYeTzPcBTcPR1A3j1hkei4pZama8kz8LKlCMv0=
cosmossdk.io/log v1.1.0/go.mod h1:6zjroETlcDs+mm62gd8Ig7mZ+N+fVOZS91V17H+M4N4=
cosmossdk.io/math v1.0.0 h1:ro9w7eKx23om2tZz/VM2Pf+z2WAbGX1yDQQOJ6iGeJw=
cosmossdk.io/math v1.0.0/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k=
cosmossdk.io/x/tx v0.5.5 h1:9XG3KOrqObt7Rw7KhT7fiqRd6EepUfmA9ERa8CHj1WM=
cosmossdk.io/x/tx v0.5.5/go.mod h1:Oh3Kh+IPOfMEILNxVd2e8SLqRrIjYHpdGBfDg4ghU/k=
cosmossdk.io/x/tx v0.6.1 h1:WwPkb7bfxGqrCKgPZuL6oW/9R51ufeFzWaXwIva6dVk=
cosmossdk.io/x/tx v0.6.1/go.mod h1:ps6ZlSuAjZFvHjZb7Kqp51Kf/UHQ/nEdEbjzXaYUhIk=
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=

View File

@ -81,13 +81,12 @@ func NewRootCmd() *cobra.Command {
// This needs to go after ReadFromClientConfig, as that function
// sets the RPC client needed for SIGN_MODE_TEXTUAL.
opts, err := txmodule.NewSignModeOptionsWithMetadataQueryFn(txmodule.NewGRPCCoinMetadataQueryFn(initClientCtx))
if err != nil {
return err
txConfigOpts := tx.ConfigOptions{
TextualCoinMetadataQueryFn: txmodule.NewGRPCCoinMetadataQueryFn(initClientCtx),
}
txConfigWithTextual := tx.NewTxConfigWithOptions(
codec.NewProtoCodec(encodingConfig.InterfaceRegistry),
opts,
txConfigOpts,
)
initClientCtx = initClientCtx.WithTxConfig(txConfigWithTextual)

View File

@ -13,7 +13,7 @@ require (
cosmossdk.io/x/evidence v0.1.0
cosmossdk.io/x/feegrant v0.0.0-20230117113717-50e7c4a4ceff
cosmossdk.io/x/nft v0.0.0-20230113085233-fae3332d62fc
cosmossdk.io/x/tx v0.5.5
cosmossdk.io/x/tx v0.6.1
cosmossdk.io/x/upgrade v0.0.0-20230127052425-54c8e1568335
github.com/cometbft/cometbft v0.37.1
github.com/cosmos/cosmos-db v1.0.0-rc.1
@ -200,6 +200,9 @@ replace (
cosmossdk.io/x/upgrade => ../x/upgrade
)
// temporary replace
replace cosmossdk.io/x/tx => ../x/tx
// Below are the long-lived replace for tests.
replace (
// We always want to test against the latest version of the simapp.

View File

@ -202,8 +202,6 @@ cosmossdk.io/log v1.1.0 h1:v0ogPHYeTzPcBTcPR1A3j1hkei4pZama8kz8LKlCMv0=
cosmossdk.io/log v1.1.0/go.mod h1:6zjroETlcDs+mm62gd8Ig7mZ+N+fVOZS91V17H+M4N4=
cosmossdk.io/math v1.0.0 h1:ro9w7eKx23om2tZz/VM2Pf+z2WAbGX1yDQQOJ6iGeJw=
cosmossdk.io/math v1.0.0/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k=
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=

View File

@ -12,6 +12,7 @@ import (
"cosmossdk.io/x/evidence"
feegrantmodule "cosmossdk.io/x/feegrant/module"
"cosmossdk.io/x/tx/decode"
txsigning "cosmossdk.io/x/tx/signing"
"cosmossdk.io/x/upgrade"
"github.com/cosmos/cosmos-sdk/codec/legacy"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
@ -114,7 +115,12 @@ func TestDecode(t *testing.T) {
tx := txBuilder.GetTx()
txBytes, err := encCfg.TxConfig.TxEncoder()(tx)
require.NoError(t, err)
decodeCtx, err := decode.NewDecoder(decode.Options{})
signContext, err := txsigning.NewContext(txsigning.Options{
AddressCodec: dummyAddressCodec{},
ValidatorAddressCodec: dummyAddressCodec{},
})
require.NoError(t, err)
decodeCtx, err := decode.NewDecoder(decode.Options{SigningContext: signContext})
require.NoError(t, err)
decodedTx, err := decodeCtx.Decode(txBytes)
require.NoError(t, err)
@ -139,3 +145,13 @@ func TestDecode(t *testing.T) {
})
}
}
type dummyAddressCodec struct{}
func (d dummyAddressCodec) StringToBytes(text string) ([]byte, error) {
return []byte(text), nil
}
func (d dummyAddressCodec) BytesToString(bz []byte) (string, error) {
return string(bz), nil
}

View File

@ -23,7 +23,7 @@ require (
cosmossdk.io/depinject v1.0.0-alpha.3 // indirect
cosmossdk.io/errors v1.0.0-beta.7 // indirect
cosmossdk.io/store v0.1.0-alpha.1.0.20230328185921-37ba88872dbc // indirect
cosmossdk.io/x/tx v0.5.5 // indirect
cosmossdk.io/x/tx v0.6.1 // indirect
filippo.io/edwards25519 v1.0.0 // indirect
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/99designs/keyring v1.2.1 // indirect
@ -139,5 +139,8 @@ require (
sigs.k8s.io/yaml v1.3.0 // indirect
)
// this seems to be required
replace github.com/cosmos/cosmos-sdk => ../..
// TODO: remove after merge of https://github.com/cosmos/cosmos-sdk/pull/15873 and tagging releases
replace (
github.com/cosmos/cosmos-sdk => ../..
cosmossdk.io/x/tx => ../../x/tx
)

View File

@ -51,8 +51,8 @@ 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=
cosmossdk.io/x/tx v0.6.1 h1:WwPkb7bfxGqrCKgPZuL6oW/9R51ufeFzWaXwIva6dVk=
cosmossdk.io/x/tx v0.6.1/go.mod h1:ps6ZlSuAjZFvHjZb7Kqp51Kf/UHQ/nEdEbjzXaYUhIk=
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=
@ -172,6 +172,8 @@ github.com/cosmos/cosmos-db v1.0.0-rc.1 h1:SjnT8B6WKMW9WEIX32qMhnEEKcI7ZP0+G1Sa9
github.com/cosmos/cosmos-db v1.0.0-rc.1/go.mod h1:Dnmk3flSf5lkwCqvvjNpoxjpXzhxnCAFzKHlbaForso=
github.com/cosmos/cosmos-proto v1.0.0-beta.3 h1:VitvZ1lPORTVxkmF2fAp3IiA61xVwArQYKXTdEcpW6o=
github.com/cosmos/cosmos-proto v1.0.0-beta.3/go.mod h1:t8IASdLaAq+bbHbjq4p960BvcTqtwuAxid3b/2rOD6I=
github.com/cosmos/cosmos-sdk v0.46.0-beta2.0.20230424095137-b73c17cb9cc8 h1:zIl1WnrW5ZP1VwhpbwVBZtCntkNKYNIkg4233/dZ3BU=
github.com/cosmos/cosmos-sdk v0.46.0-beta2.0.20230424095137-b73c17cb9cc8/go.mod h1:JicgV9n3SAu5uuoyDvQ2gSHYLyFvyRrIUYB5T2Q4HRw=
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=

View File

@ -132,11 +132,13 @@ func TestSigVerification(t *testing.T) {
enabledSignModes := []signing.SignMode{signing.SignMode_SIGN_MODE_DIRECT, signing.SignMode_SIGN_MODE_TEXTUAL, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON}
// Since TEXTUAL is not enabled by default, we create a custom TxConfig
// here which includes it.
opts, err := txmodule.NewSignModeOptionsWithMetadataQueryFn(txmodule.NewGRPCCoinMetadataQueryFn(suite.clientCtx))
require.NoError(t, err)
txConfigOpts := authtx.ConfigOptions{
TextualCoinMetadataQueryFn: txmodule.NewGRPCCoinMetadataQueryFn(suite.clientCtx),
EnabledSignModes: enabledSignModes,
}
suite.clientCtx.TxConfig = authtx.NewTxConfigWithOptions(
codec.NewProtoCodec(suite.encCfg.InterfaceRegistry),
opts,
txConfigOpts,
)
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
@ -163,11 +165,13 @@ func TestSigVerification(t *testing.T) {
gasLimit := testdata.NewTestGasLimit()
spkd := ante.NewSetPubKeyDecorator(suite.accountKeeper)
opts, err = txmodule.NewSignModeOptionsWithMetadataQueryFn(txmodule.NewBankKeeperCoinMetadataQueryFn(suite.txBankKeeper))
require.NoError(t, err)
txConfigOpts = authtx.ConfigOptions{
TextualCoinMetadataQueryFn: txmodule.NewBankKeeperCoinMetadataQueryFn(suite.txBankKeeper),
EnabledSignModes: enabledSignModes,
}
anteTxConfig := authtx.NewTxConfigWithOptions(
codec.NewProtoCodec(suite.encCfg.InterfaceRegistry),
opts,
txConfigOpts,
)
svd := ante.NewSigVerificationDecorator(suite.accountKeeper, anteTxConfig.SignModeHandler())
antehandler := sdk.ChainAnteDecorators(spkd, svd)

View File

@ -10,14 +10,12 @@ import (
"google.golang.org/protobuf/types/known/anypb"
errorsmod "cosmossdk.io/errors"
"cosmossdk.io/x/tx/decode"
txsigning "cosmossdk.io/x/tx/signing"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/types/registry"
txsigning "cosmossdk.io/x/tx/signing"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
@ -117,11 +115,6 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) (err error) {
txFactory = txFactory.WithAccountNumber(accnum).WithSequence(seq)
}
decoder, err := decode.NewDecoder(decode.Options{ProtoFiles: registry.MergedProtoRegistry()})
if err != nil {
return err
}
// read each signature and add it to the multisig if valid
for i := 2; i < len(args); i++ {
sigs, err := unmarshalSignatureJSON(clientCtx, args[i])
@ -148,20 +141,12 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) (err error) {
Value: anyPk.Value,
},
}
txBytes, err := txCfg.TxEncoder()(txBuilder.GetTx())
if err != nil {
return err
}
decodedTx, err := decoder.Decode(txBytes)
if err != nil {
return err
}
txData := txsigning.TxData{
Body: decodedTx.Tx.Body,
AuthInfo: decodedTx.Tx.AuthInfo,
AuthInfoBytes: decodedTx.TxRaw.AuthInfoBytes,
BodyBytes: decodedTx.TxRaw.BodyBytes,
builtTx := txBuilder.GetTx()
adaptableTx, ok := builtTx.(signing.V2AdaptableTx)
if !ok {
return fmt.Errorf("expected Tx to be signing.V2AdaptableTx, got %T", builtTx)
}
txData := adaptableTx.GetSigningTxData()
err = signing.VerifySignature(cmd.Context(), sig.PubKey, txSignerData, sig.Data,
txCfg.SignModeHandler(), txData)
@ -343,24 +328,13 @@ func makeBatchMultisignCmd() func(cmd *cobra.Command, args []string) error {
},
}
txBytes, err := txCfg.TxEncoder()(txBldr.GetTx())
if err != nil {
return err
}
decodeCtx, err := decode.NewDecoder(decode.Options{ProtoFiles: registry.MergedProtoRegistry()})
if err != nil {
return err
}
decodedTx, err := decodeCtx.Decode(txBytes)
if err != nil {
return err
}
txData := txsigning.TxData{
Body: decodedTx.Tx.Body,
AuthInfo: decodedTx.Tx.AuthInfo,
AuthInfoBytes: decodedTx.TxRaw.AuthInfoBytes,
BodyBytes: decodedTx.TxRaw.BodyBytes,
builtTx := txBldr.GetTx()
adaptableTx, ok := builtTx.(signing.V2AdaptableTx)
if !ok {
return fmt.Errorf("expected Tx to be signing.V2AdaptableTx, got %T", builtTx)
}
txData := adaptableTx.GetSigningTxData()
for _, sig := range signatureBatch {
err = signing.VerifySignature(cmd.Context(), sig[i].PubKey, txSignerData, sig[i].Data,
txCfg.SignModeHandler(), txData)

View File

@ -6,14 +6,12 @@ import (
"github.com/spf13/cobra"
"google.golang.org/protobuf/types/known/anypb"
"cosmossdk.io/x/tx/decode"
txsigning "cosmossdk.io/x/tx/signing"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/registry"
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
)
@ -132,27 +130,12 @@ func printAndValidateSigs(
},
}
txBytes, err := clientCtx.TxConfig.TxEncoder()(tx)
if err != nil {
cmd.PrintErrf("failed to encode transaction: %v", err)
adaptableTx, ok := tx.(authsigning.V2AdaptableTx)
if !ok {
cmd.PrintErrf("expected V2AdaptableTx, got %T", tx)
return false
}
decodeCtx, err := decode.NewDecoder(decode.Options{ProtoFiles: registry.MergedProtoRegistry()})
if err != nil {
cmd.PrintErrf("failed to create decoder: %v", err)
return false
}
decodedTx, err := decodeCtx.Decode(txBytes)
if err != nil {
cmd.PrintErrf("failed to decode transaction: %v", err)
return false
}
txData := txsigning.TxData{
Body: decodedTx.Tx.Body,
AuthInfo: decodedTx.Tx.AuthInfo,
AuthInfoBytes: decodedTx.TxRaw.AuthInfoBytes,
BodyBytes: decodedTx.TxRaw.BodyBytes,
}
txData := adaptableTx.GetSigningTxData()
err = authsigning.VerifySignature(cmd.Context(), pubKey, txSignerData, sig.Data, signModeHandler, txData)
if err != nil {

View File

@ -1,4 +1,4 @@
package keeper
package codec
import (
"errors"

View File

@ -16,6 +16,7 @@ import (
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
@ -65,6 +66,7 @@ type AccountKeeper struct {
storeService store.KVStoreService
cdc codec.BinaryCodec
permAddrs map[string]types.PermissionsForAddress
bech32Prefix string
// The prototypical AccountI constructor.
proto func() sdk.AccountI
@ -98,7 +100,8 @@ func NewAccountKeeper(
sb := collections.NewSchemaBuilder(storeService)
return AccountKeeper{
Codec: NewBech32Codec(bech32Prefix),
Codec: authcodec.NewBech32Codec(bech32Prefix),
bech32Prefix: bech32Prefix,
storeService: storeService,
proto: proto,
cdc: cdc,
@ -256,12 +259,7 @@ func (ak AccountKeeper) GetCodec() codec.BinaryCodec { return ak.cdc }
// add getter for bech32Prefix
func (ak AccountKeeper) getBech32Prefix() (string, error) {
bech32Codec, ok := ak.Codec.(bech32Codec)
if !ok {
return "", fmt.Errorf("unable cast addressCdc to bech32Codec; expected %T got %T", bech32Codec, ak.Codec)
}
return bech32Codec.bech32Prefix, nil
return ak.bech32Prefix, nil
}
// SetParams sets the auth module's parameters.

View File

@ -10,6 +10,7 @@ import (
"github.com/spf13/cobra"
"cosmossdk.io/depinject"
authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec"
"cosmossdk.io/core/address"
"cosmossdk.io/core/appmodule"
@ -207,7 +208,7 @@ func init() {
// ProvideAddressCodec provides an address.Codec to the container for any
// modules that want to do address string <> bytes conversion.
func ProvideAddressCodec(config *modulev1.Module) address.Codec {
return keeper.NewBech32Codec(config.Bech32Prefix)
return authcodec.NewBech32Codec(config.Bech32Prefix)
}
type ModuleInputs struct {

View File

@ -9,11 +9,12 @@ import (
"cosmossdk.io/x/tx/signing/aminojson"
"cosmossdk.io/x/tx/signing/direct"
"cosmossdk.io/x/tx/signing/directaux"
"cosmossdk.io/x/tx/signing/textual"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec"
)
type config struct {
@ -25,12 +26,47 @@ type config struct {
protoCodec codec.ProtoCodecMarshaler
}
// ConfigOptions define the configuration of a TxConfig when calling NewTxConfigWithOptions.
// An empty struct is a valid configuration and will result in a TxConfig with default values.
type ConfigOptions struct {
// If SigningHandler is specified it will be used instead constructing one.
// This option supersedes all below options, whose sole purpose are to configure the creation of
// txsigning.HandlerMap.
SigningHandler *txsigning.HandlerMap
// EnabledSignModes is the list of sign modes that will be enabled in the txsigning.HandlerMap.
EnabledSignModes []signingtypes.SignMode
// If SigningContext is specified it will be used when constructing sign mode handlers. If nil, one will be created
// with the options specified in SigningOptions.
SigningContext *txsigning.Context
// SigningOptions are the options that will be used when constructing a txsigning.Context and sign mode handlers.
// If nil defaults will be used.
SigningOptions *txsigning.Options
// TextualCoinMetadataQueryFn is the function that will be used to query coin metadata when constructing
// textual sign mode handler. This is required if SIGN_MODE_TEXTUAL is enabled.
TextualCoinMetadataQueryFn textual.CoinMetadataQueryFn
// CustomSignModes are the custom sign modes that will be added to the txsigning.HandlerMap.
CustomSignModes []txsigning.SignModeHandler
}
// DefaultSignModes are the default sign modes enabled for protobuf transactions.
var DefaultSignModes = []signingtypes.SignMode{
signingtypes.SignMode_SIGN_MODE_DIRECT,
signingtypes.SignMode_SIGN_MODE_DIRECT_AUX,
signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
// We currently don't add SIGN_MODE_TEXTUAL as part of the default sign
// modes, as it's not released yet (including the Ledger app). However,
// textual's sign mode handler is already available in this package. If you
// want to use textual for **TESTING** purposes, feel free to create a
// handler that includes SIGN_MODE_TEXTUAL.
// ref: Tracking issue for SIGN_MODE_TEXTUAL https://github.com/cosmos/cosmos-sdk/issues/11970
}
// NewTxConfig returns a new protobuf TxConfig using the provided ProtoCodec and sign modes. The
// first enabled sign mode will become the default sign mode.
//
// NOTE: Use NewTxConfigWithHandler to provide a custom signing handler in case the sign mode
// is not supported by default (eg: SignMode_SIGN_MODE_EIP_191). Use NewTxConfigWithOptions
// to enable SIGN_MODE_TEXTUAL (for testing purposes for now).
// NOTE: Use NewTxConfigWithOptions to provide a custom signing handler in case the sign mode
// is not supported by default (eg: SignMode_SIGN_MODE_EIP_191), or to enable SIGN_MODE_TEXTUAL
// (for testing purposes for now).
//
// We prefer to use depinject to provide client.TxConfig, but we permit this constructor usage. Within the SDK,
// this constructor is primarily used in tests, but also sees usage in app chains like:
@ -38,55 +74,100 @@ type config struct {
func NewTxConfig(protoCodec codec.ProtoCodecMarshaler, enabledSignModes []signingtypes.SignMode,
customSignModes ...txsigning.SignModeHandler,
) client.TxConfig {
typeResolver := protoregistry.GlobalTypes
protoFiles := protoCodec.InterfaceRegistry()
signersContext, err := txsigning.NewGetSignersContext(txsigning.GetSignersOptions{ProtoFiles: protoFiles})
if err != nil {
panic(err)
}
signModeOptions := &SignModeOptions{}
for _, m := range enabledSignModes {
switch m {
case signingtypes.SignMode_SIGN_MODE_DIRECT:
signModeOptions.Direct = &direct.SignModeHandler{}
case signingtypes.SignMode_SIGN_MODE_DIRECT_AUX:
signModeOptions.DirectAux = &directaux.SignModeHandlerOptions{
FileResolver: protoFiles,
TypeResolver: typeResolver,
SignersContext: signersContext,
}
case signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON:
aminoJSONEncoder := aminojson.NewAminoJSON()
signModeOptions.AminoJSON = &aminojson.SignModeHandlerOptions{
FileResolver: protoFiles,
TypeResolver: typeResolver,
Encoder: &aminoJSONEncoder,
}
case signingtypes.SignMode_SIGN_MODE_TEXTUAL:
panic("cannot use NewTxConfig with SIGN_MODE_TEXTUAL enabled; please use NewTxConfigWithOptions")
}
}
return NewTxConfigWithHandler(protoCodec, makeSignModeHandler(*signModeOptions, customSignModes...))
return NewTxConfigWithOptions(protoCodec, ConfigOptions{
EnabledSignModes: enabledSignModes,
CustomSignModes: customSignModes,
})
}
func NewTxConfigWithOptions(protoCodec codec.ProtoCodecMarshaler, signModeOptions SignModeOptions,
customSignModes ...txsigning.SignModeHandler,
) client.TxConfig {
return NewTxConfigWithHandler(protoCodec, makeSignModeHandler(signModeOptions, customSignModes...))
}
// NewTxConfigWithHandler returns a new protobuf TxConfig using the provided ProtoCodec and signing handler.
func NewTxConfigWithHandler(protoCodec codec.ProtoCodecMarshaler, handler *txsigning.HandlerMap) client.TxConfig {
return &config{
handler: handler,
// NewTxConfigWithOptions returns a new protobuf TxConfig using the provided ProtoCodec, ConfigOptions and
// custom sign mode handlers. If ConfigOptions is an empty struct then default values will be used.
func NewTxConfigWithOptions(protoCodec codec.ProtoCodecMarshaler, configOptions ConfigOptions) client.TxConfig {
txConfig := &config{
decoder: DefaultTxDecoder(protoCodec),
encoder: DefaultTxEncoder(),
jsonDecoder: DefaultJSONTxDecoder(protoCodec),
jsonEncoder: DefaultJSONTxEncoder(protoCodec),
protoCodec: protoCodec,
}
opts := &configOptions
if opts.SigningHandler != nil {
txConfig.handler = opts.SigningHandler
return txConfig
}
signingOpts := opts.SigningOptions
if signingOpts == nil {
signingOpts = &txsigning.Options{}
}
if signingOpts.TypeResolver == nil {
signingOpts.TypeResolver = protoregistry.GlobalTypes
}
if signingOpts.FileResolver == nil {
signingOpts.FileResolver = protoCodec.InterfaceRegistry()
}
if len(opts.EnabledSignModes) == 0 {
opts.EnabledSignModes = DefaultSignModes
}
if opts.SigningContext == nil {
sdkConfig := sdk.GetConfig()
if signingOpts.AddressCodec == nil {
signingOpts.AddressCodec = authcodec.NewBech32Codec(sdkConfig.GetBech32AccountAddrPrefix())
}
if signingOpts.ValidatorAddressCodec == nil {
signingOpts.ValidatorAddressCodec = authcodec.NewBech32Codec(sdkConfig.GetBech32ValidatorAddrPrefix())
}
var err error
opts.SigningContext, err = txsigning.NewContext(*signingOpts)
if err != nil {
panic(err)
}
}
lenSignModes := len(configOptions.EnabledSignModes)
handlers := make([]txsigning.SignModeHandler, lenSignModes+len(opts.CustomSignModes))
for i, m := range configOptions.EnabledSignModes {
var err error
switch m {
case signingtypes.SignMode_SIGN_MODE_DIRECT:
handlers[i] = &direct.SignModeHandler{}
case signingtypes.SignMode_SIGN_MODE_DIRECT_AUX:
handlers[i], err = directaux.NewSignModeHandler(directaux.SignModeHandlerOptions{
TypeResolver: signingOpts.TypeResolver,
SignersContext: opts.SigningContext,
})
if err != nil {
panic(err)
}
case signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON:
aminoJSONEncoder := aminojson.NewAminoJSON()
handlers[i] = aminojson.NewSignModeHandler(aminojson.SignModeHandlerOptions{
FileResolver: signingOpts.FileResolver,
TypeResolver: signingOpts.TypeResolver,
Encoder: &aminoJSONEncoder,
})
case signingtypes.SignMode_SIGN_MODE_TEXTUAL:
handlers[i], err = textual.NewSignModeHandler(textual.SignModeOptions{
CoinMetadataQuerier: opts.TextualCoinMetadataQueryFn,
FileResolver: signingOpts.FileResolver,
TypeResolver: signingOpts.TypeResolver,
})
if opts.TextualCoinMetadataQueryFn == nil {
panic("cannot enable SIGN_MODE_TEXTUAL without a TextualCoinMetadataQueryFn")
}
if err != nil {
panic(err)
}
}
}
for i, m := range opts.CustomSignModes {
handlers[i+lenSignModes] = m
}
txConfig.handler = txsigning.NewHandlerMap(handlers...)
return txConfig
}
func (g config) NewTxBuilder() client.TxBuilder {

View File

@ -7,17 +7,14 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
grpcstatus "google.golang.org/grpc/status"
"google.golang.org/protobuf/reflect/protoregistry"
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
txconfigv1 "cosmossdk.io/api/cosmos/tx/config/v1"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/depinject"
txsigning "cosmossdk.io/x/tx/signing"
"cosmossdk.io/x/tx/signing/aminojson"
"cosmossdk.io/x/tx/signing/direct"
"cosmossdk.io/x/tx/signing/directaux"
"cosmossdk.io/x/tx/signing/textual"
authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
@ -35,7 +32,7 @@ import (
func init() {
appmodule.Register(&txconfigv1.Config{},
appmodule.Provide(ProvideModule),
appmodule.Provide(ProvideSignModeOptions),
appmodule.Provide(ProvideProtoRegistry),
)
}
@ -43,7 +40,7 @@ type ModuleInputs struct {
depinject.In
Config *txconfigv1.Config
ProtoCodecMarshaler codec.ProtoCodecMarshaler
SignModeOptions tx.SignModeOptions
ProtoFileResolver txsigning.ProtoFileResolver
// BankKeeper is the expected bank keeper to be passed to AnteHandlers
BankKeeper authtypes.BankKeeper `optional:"true"`
AccountKeeper ante.AccountKeeper `optional:"true"`
@ -58,22 +55,29 @@ type ModuleOutputs struct {
BaseAppOption runtime.BaseAppOption
}
// ProvideSignModeOptions provides the default x/tx SignModeOptions for the SDK.
func ProvideSignModeOptions(bk BankKeeper) tx.SignModeOptions {
opts, err := NewSignModeOptionsWithMetadataQueryFn(NewBankKeeperCoinMetadataQueryFn(bk))
if err != nil {
panic(err)
}
return opts
func ProvideProtoRegistry() txsigning.ProtoFileResolver {
return registry.MergedProtoRegistry()
}
func ProvideModule(in ModuleInputs) ModuleOutputs {
var txConfig client.TxConfig
var customSignModeHandlers []txsigning.SignModeHandler
if in.CustomSignModeHandlers != nil {
customSignModeHandlers = in.CustomSignModeHandlers()
}
txConfig = tx.NewTxConfigWithOptions(in.ProtoCodecMarshaler, in.SignModeOptions, customSignModeHandlers...)
sdkConfig := sdk.GetConfig()
txConfigOptions := tx.ConfigOptions{
SigningOptions: &txsigning.Options{
FileResolver: in.ProtoFileResolver,
// From static config? But this is already in auth config.
// - Provide codecs there as types?
// - Provide static prefix there exported from config?
// - Just do as below?
AddressCodec: authcodec.NewBech32Codec(sdkConfig.GetBech32AccountAddrPrefix()),
ValidatorAddressCodec: authcodec.NewBech32Codec(sdkConfig.GetBech32ValidatorAddrPrefix()),
},
CustomSignModes: customSignModeHandlers,
}
txConfig := tx.NewTxConfigWithOptions(in.ProtoCodecMarshaler, txConfigOptions)
baseAppOption := func(app *baseapp.BaseApp) {
// AnteHandlers
@ -197,38 +201,6 @@ func NewGRPCCoinMetadataQueryFn(grpcConn grpc.ClientConnInterface) textual.CoinM
}
}
// NewSignModeOptionsWithMetadataQueryFn creates a new SignModeOptions instance
func NewSignModeOptionsWithMetadataQueryFn(fn textual.CoinMetadataQueryFn) (tx.SignModeOptions, error) {
protoFiles := registry.MergedProtoRegistry()
typeResolver := protoregistry.GlobalTypes
signersContext, err := txsigning.NewGetSignersContext(txsigning.GetSignersOptions{ProtoFiles: protoFiles})
if err != nil {
return tx.SignModeOptions{}, err
}
aminoJSONEncoder := aminojson.NewAminoJSON()
signModeOptions := tx.SignModeOptions{
Direct: &direct.SignModeHandler{},
DirectAux: &directaux.SignModeHandlerOptions{
FileResolver: protoFiles,
TypeResolver: typeResolver,
SignersContext: signersContext,
},
AminoJSON: &aminojson.SignModeHandlerOptions{
FileResolver: protoFiles,
TypeResolver: typeResolver,
Encoder: &aminoJSONEncoder,
},
Textual: &textual.SignModeOptions{
CoinMetadataQuerier: fn,
FileResolver: protoFiles,
TypeResolver: typeResolver,
},
}
return signModeOptions, nil
}
// metadataExists parses the error, and only propagates the error if it's
// different than a "not found" error.
func metadataExists(err error) error {

View File

@ -1,65 +0,0 @@
package tx
import (
txsigning "cosmossdk.io/x/tx/signing"
"cosmossdk.io/x/tx/signing/aminojson"
"cosmossdk.io/x/tx/signing/direct"
"cosmossdk.io/x/tx/signing/directaux"
"cosmossdk.io/x/tx/signing/textual"
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
)
type SignModeOptions struct {
// Textual are options for SIGN_MODE_TEXTUAL
Textual *textual.SignModeOptions
// DirectAux are options for SIGN_MODE_DIRECT_AUX
DirectAux *directaux.SignModeHandlerOptions
// AminoJSON are options for SIGN_MODE_LEGACY_AMINO_JSON
AminoJSON *aminojson.SignModeHandlerOptions
// Direct is the SignModeHandler for SIGN_MODE_DIRECT since it takes options
Direct *direct.SignModeHandler
}
// DefaultSignModes are the default sign modes enabled for protobuf transactions.
var DefaultSignModes = []signingtypes.SignMode{
signingtypes.SignMode_SIGN_MODE_DIRECT,
signingtypes.SignMode_SIGN_MODE_DIRECT_AUX,
signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
// We currently don't add SIGN_MODE_TEXTUAL as part of the default sign
// modes, as it's not released yet (including the Ledger app). However,
// textual's sign mode handler is already available in this package. If you
// want to use textual for **TESTING** purposes, feel free to create a
// handler that includes SIGN_MODE_TEXTUAL.
// ref: Tracking issue for SIGN_MODE_TEXTUAL https://github.com/cosmos/cosmos-sdk/issues/11970
}
// makeSignModeHandler returns the default protobuf SignModeHandler supporting
// SIGN_MODE_DIRECT, SIGN_MODE_DIRECT_AUX and SIGN_MODE_LEGACY_AMINO_JSON.
func makeSignModeHandler(
opts SignModeOptions,
customSignModes ...txsigning.SignModeHandler,
) *txsigning.HandlerMap {
var handlers []txsigning.SignModeHandler
if opts.Direct != nil {
handlers = append(handlers, opts.Direct)
}
if opts.Textual != nil {
h, err := textual.NewSignModeHandler(*opts.Textual)
if err != nil {
panic(err)
}
handlers = append(handlers, h)
}
if opts.DirectAux != nil {
h, err := directaux.NewSignModeHandler(*opts.DirectAux)
if err != nil {
panic(err)
}
handlers = append(handlers, h)
}
if opts.AminoJSON != nil {
handlers = append(handlers, aminojson.NewSignModeHandler(*opts.AminoJSON))
}
handlers = append(handlers, customSignModes...)
return txsigning.NewHandlerMap(handlers...)
}

View File

@ -163,7 +163,7 @@ func convertToNewVotes(oldVotes v1beta1.Votes) (v1.Votes, error) {
newWVOs = v1.NewNonSplitVoteOption(v1.VoteOption(oldVote.Option))
default:
return nil, fmt.Errorf("vote does not have neither Options nor Option")
return nil, fmt.Errorf("vote does not have neither InterfaceRegistryOptions nor Option")
}
newVotes[i] = &v1.Vote{

View File

@ -2929,7 +2929,7 @@ func (m *Vote) Unmarshal(dAtA []byte) error {
iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field InterfaceRegistryOptions", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {

View File

@ -2814,7 +2814,7 @@ func (m *MsgVoteWeighted) Unmarshal(dAtA []byte) error {
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field InterfaceRegistryOptions", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {

View File

@ -2373,7 +2373,7 @@ func (m *Vote) Unmarshal(dAtA []byte) error {
}
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field InterfaceRegistryOptions", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {

View File

@ -1538,7 +1538,7 @@ func (m *MsgVoteWeighted) Unmarshal(dAtA []byte) error {
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field InterfaceRegistryOptions", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {

View File

@ -31,6 +31,12 @@ Ref: https://keepachangelog.com/en/1.0.0/
## Unreleased
### Improvements
* [#15873](https://github.com/cosmos/cosmos-sdk/pull/15873): add `Validate` method and only check for errors when `Validate` is explicitly called.
## v0.6.0
### API Breaking
* [#15709](https://github.com/cosmos/cosmos-sdk/pull/15709):

View File

@ -4,15 +4,14 @@ import (
"errors"
"fmt"
"cosmossdk.io/core/address"
cosmos_proto "github.com/cosmos/cosmos-proto"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protodesc"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/types/dynamicpb"
msgv1 "cosmossdk.io/api/cosmos/msg/v1"
"cosmossdk.io/core/address"
)
// Context is a context for retrieving the list of signers from a
@ -78,7 +77,7 @@ func NewContext(options Options) (*Context, error) {
getSignersFuncs: map[protoreflect.FullName]getSignersFunc{},
}
return c, c.init()
return c, nil
}
type getSignersFunc func(proto.Message) ([][]byte, error)
@ -92,26 +91,25 @@ func getSignersFieldNames(descriptor protoreflect.MessageDescriptor) ([]string,
return signersFields, nil
}
// init performs a dry run of getting all msg's signers. This has 2 benefits:
// Validate performs a dry run of getting all msg's signers. This has 2 benefits:
// - it will error if any Msg has forgotten the "cosmos.msg.v1.signer"
// annotation
// - it will pre-populate the context's internal cache for getSignersFuncs
// so that calling it in antehandlers will be faster.
func (c *Context) init() error {
func (c *Context) Validate() error {
var errs []error
c.fileResolver.RangeFiles(func(fd protoreflect.FileDescriptor) bool {
for i := 0; i < fd.Services().Len(); i++ {
sd := fd.Services().Get(i)
// We use the heuristic that services named "Msg" are exactly the
// ones that need the proto annotation check.
if sd.Name() != "Msg" {
// Skip services that are not annotated with the "cosmos.msg.v1.service" option.
if ext := proto.GetExtension(sd.Options(), msgv1.E_Service); ext == nil || !ext.(bool) {
continue
}
for j := 0; j < sd.Methods().Len(); j++ {
md := sd.Methods().Get(j).Input()
msg := dynamicpb.NewMessage(md)
_, err := c.GetSigners(msg)
_, err := c.getGetSignersFn(md)
if err != nil {
errs = append(errs, err)
}
@ -284,9 +282,7 @@ func (c *Context) getAddressCodec(field protoreflect.FieldDescriptor) address.Co
return addrCdc
}
// GetSigners returns the signers for a given message.
func (c *Context) GetSigners(msg proto.Message) ([][]byte, error) {
messageDescriptor := msg.ProtoReflect().Descriptor()
func (c *Context) getGetSignersFn(messageDescriptor protoreflect.MessageDescriptor) (getSignersFunc, error) {
f, ok := c.getSignersFuncs[messageDescriptor.FullName()]
if !ok {
var err error
@ -297,6 +293,16 @@ func (c *Context) GetSigners(msg proto.Message) ([][]byte, error) {
c.getSignersFuncs[messageDescriptor.FullName()] = f
}
return f, nil
}
// GetSigners returns the signers for a given message.
func (c *Context) GetSigners(msg proto.Message) ([][]byte, error) {
f, err := c.getGetSignersFn(msg.ProtoReflect().Descriptor())
if err != nil {
return nil, err
}
return f(msg)
}