feat!(x/tx): support validator address signers (#15709)

This commit is contained in:
Aaron Craelius 2023-04-12 12:33:04 -04:00 committed by GitHub
parent bf17fec0e7
commit 001c11e00d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 1139 additions and 475 deletions

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.1-0.20230407182919-057d2e09bd63
cosmossdk.io/x/tx v0.5.1
cosmossdk.io/x/upgrade v0.0.0-20230127052425-54c8e1568335
github.com/cometbft/cometbft v0.37.1-0.20230411132551-3a91d155e664
github.com/cosmos/cosmos-db v1.0.0-rc.1
@ -197,7 +197,6 @@ replace (
cosmossdk.io/x/evidence => ../x/evidence
cosmossdk.io/x/feegrant => ../x/feegrant
cosmossdk.io/x/nft => ../x/nft
cosmossdk.io/x/tx => ../x/tx
cosmossdk.io/x/upgrade => ../x/upgrade
)

View File

@ -202,6 +202,8 @@ cosmossdk.io/log v1.0.0 h1:NGKZ/A5rd4PduDfoscgABklX557PWjQINbosZy/m3Jk=
cosmossdk.io/log v1.0.0/go.mod h1:CwX9BLiBruZb7lzLlRr3R231d/fVPUXk8gAdV4LQap0=
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.1 h1:OcHU8ex3JzxDjexSkMovBx8EnJXcqhrRt7msBq/3vqs=
cosmossdk.io/x/tx v0.5.1/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

@ -31,10 +31,22 @@ Ref: https://keepachangelog.com/en/1.0.0/
## Unreleased
### API Breaking
* [#15709](https://github.com/cosmos/cosmos-sdk/pull/15709):
* `GetSignersContext` has been renamed to `signing.Context`
* `GetSigners` now returns `[][]byte` instead of `[]string`
* `GetSignersOptions` has been renamed to `signing.Options` and requires `address.Codec`s for account and validator addresses
* `GetSignersOptions.ProtoFiles` has been renamed to `signing.Options.FileResolver`
## v0.5.1
### Features
* [#15414](https://github.com/cosmos/cosmos-sdk/pull/15414) Add basic transaction decoding support.
## v0.5.0
### API Breaking
* [#15581](https://github.com/cosmos/cosmos-sdk/pull/15581) `GetSignersOptions` and `directaux.SignModeHandlerOptions` now

View File

@ -1,12 +1,13 @@
package decode
import (
"github.com/cosmos/cosmos-proto/anyutil"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoregistry"
"fmt"
v1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1"
"cosmossdk.io/errors"
"github.com/cosmos/cosmos-proto/anyutil"
"google.golang.org/protobuf/proto"
"cosmossdk.io/x/tx/signing"
)
@ -15,51 +16,28 @@ type DecodedTx struct {
Messages []proto.Message
Tx *v1beta1.Tx
TxRaw *v1beta1.TxRaw
Signers []string
Signers [][]byte
TxBodyHasUnknownNonCriticals bool
}
// Decoder contains the dependencies required for decoding transactions.
type Decoder struct {
getSignersCtx *signing.GetSignersContext
typeResolver protoregistry.MessageTypeResolver
protoFiles *protoregistry.Files
signingCtx *signing.Context
}
// Options are options for creating a Decoder.
type Options struct {
// ProtoFiles are the protobuf files to use for resolving message descriptors.
// If it is nil, the global protobuf registry will be used.
ProtoFiles *protoregistry.Files
TypeResolver protoregistry.MessageTypeResolver
SigningContext *signing.GetSignersContext
SigningContext *signing.Context
}
// NewDecoder creates a new Decoder for decoding transactions.
func NewDecoder(options Options) (*Decoder, error) {
if options.ProtoFiles == nil {
options.ProtoFiles = protoregistry.GlobalFiles
}
if options.TypeResolver == nil {
options.TypeResolver = protoregistry.GlobalTypes
}
getSignersCtx := options.SigningContext
if getSignersCtx == nil {
var err error
getSignersCtx, err = signing.NewGetSignersContext(signing.GetSignersOptions{
ProtoFiles: options.ProtoFiles,
})
if err != nil {
return nil, err
}
if options.SigningContext == nil {
return nil, fmt.Errorf("signing context is required")
}
return &Decoder{
getSignersCtx: getSignersCtx,
protoFiles: options.ProtoFiles,
typeResolver: options.TypeResolver,
signingCtx: options.SigningContext,
}, nil
}
@ -74,7 +52,8 @@ func (d *Decoder) Decode(txBytes []byte) (*DecodedTx, error) {
var raw v1beta1.TxRaw
// reject all unknown proto fields in the root TxRaw
err = RejectUnknownFieldsStrict(txBytes, raw.ProtoReflect().Descriptor(), d.protoFiles)
fileResolver := d.signingCtx.FileResolver()
err = RejectUnknownFieldsStrict(txBytes, raw.ProtoReflect().Descriptor(), fileResolver)
if err != nil {
return nil, errors.Wrap(ErrTxDecode, err.Error())
}
@ -87,7 +66,7 @@ func (d *Decoder) Decode(txBytes []byte) (*DecodedTx, error) {
var body v1beta1.TxBody
// allow non-critical unknown fields in TxBody
txBodyHasUnknownNonCriticals, err := RejectUnknownFields(raw.BodyBytes, body.ProtoReflect().Descriptor(), true, d.protoFiles)
txBodyHasUnknownNonCriticals, err := RejectUnknownFields(raw.BodyBytes, body.ProtoReflect().Descriptor(), true, fileResolver)
if err != nil {
return nil, errors.Wrap(ErrTxDecode, err.Error())
}
@ -100,7 +79,7 @@ func (d *Decoder) Decode(txBytes []byte) (*DecodedTx, error) {
var authInfo v1beta1.AuthInfo
// reject all unknown proto fields in AuthInfo
err = RejectUnknownFieldsStrict(raw.AuthInfoBytes, authInfo.ProtoReflect().Descriptor(), d.protoFiles)
err = RejectUnknownFieldsStrict(raw.AuthInfoBytes, authInfo.ProtoReflect().Descriptor(), fileResolver)
if err != nil {
return nil, errors.Wrap(ErrTxDecode, err.Error())
}
@ -116,15 +95,15 @@ func (d *Decoder) Decode(txBytes []byte) (*DecodedTx, error) {
Signatures: raw.Signatures,
}
var signers []string
var signers [][]byte
var msgs []proto.Message
for _, anyMsg := range body.Messages {
msg, signerErr := anyutil.Unpack(anyMsg, d.protoFiles, d.typeResolver)
msg, signerErr := anyutil.Unpack(anyMsg, fileResolver, d.signingCtx.TypeResolver())
if signerErr != nil {
return nil, errors.Wrap(ErrTxDecode, signerErr.Error())
}
msgs = append(msgs, msg)
ss, signerErr := d.getSignersCtx.GetSigners(msg)
ss, signerErr := d.signingCtx.GetSigners(msg)
if signerErr != nil {
return nil, errors.Wrap(ErrTxDecode, signerErr.Error())
}

View File

@ -1,6 +1,7 @@
package decode_test
import (
"encoding/hex"
"fmt"
"testing"
@ -9,8 +10,10 @@ import (
"cosmossdk.io/api/cosmos/crypto/secp256k1"
signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1"
txv1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1"
"cosmossdk.io/x/tx/decode"
"cosmossdk.io/x/tx/internal/testpb"
"cosmossdk.io/x/tx/signing"
"github.com/cosmos/cosmos-proto/anyutil"
"github.com/stretchr/testify/require"
@ -36,6 +39,16 @@ func TestDecode(t *testing.T) {
Sequence: accSeq,
})
signingCtx, err := signing.NewContext(signing.Options{
AddressCodec: dummyAddressCodec{},
ValidatorAddressCodec: dummyAddressCodec{},
})
require.NoError(t, err)
decoder, err := decode.NewDecoder(decode.Options{
SigningContext: signingCtx,
})
require.NoError(t, err)
testCases := []struct {
name string
msg proto.Message
@ -83,9 +96,6 @@ func TestDecode(t *testing.T) {
txBytes, err := proto.Marshal(tx)
require.NoError(t, err)
decoder, err := decode.NewDecoder(decode.Options{})
require.NoError(t, err)
decodeTx, err := decoder.Decode(txBytes)
if tc.error != "" {
require.EqualError(t, err, tc.error)
@ -99,3 +109,13 @@ func TestDecode(t *testing.T) {
})
}
}
type dummyAddressCodec struct{}
func (d dummyAddressCodec) StringToBytes(text string) ([]byte, error) {
return hex.DecodeString(text)
}
func (d dummyAddressCodec) BytesToString(bz []byte) (string, error) {
return hex.EncodeToString(bz), nil
}

View File

@ -1,6 +1,7 @@
syntax = "proto3";
import "cosmos/msg/v1/msg.proto";
import "cosmos_proto/cosmos.proto";
option go_package = "cosmossdk.io/x/tx/internal/testpb";
@ -58,6 +59,12 @@ message BadSigner {
option (cosmos.msg.v1.signer) = "signer";
bytes signer = 1;
}
message NoSignerOption {
bytes signer = 1;
}
message ValidatorSigner {
option (cosmos.msg.v1.signer) = "signer";
string signer = 1 [(cosmos_proto.scalar) = "cosmos.ValidatorAddressString"];
}

View File

@ -4,6 +4,7 @@ package testpb
import (
_ "cosmossdk.io/api/cosmos/msg/v1"
fmt "fmt"
_ "github.com/cosmos/cosmos-proto"
runtime "github.com/cosmos/cosmos-proto/runtime"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoiface "google.golang.org/protobuf/runtime/protoiface"
@ -1368,7 +1369,7 @@ func (x *NestedSigner_Inner) ProtoReflect() protoreflect.Message {
}
func (x *NestedSigner_Inner) slowProtoReflect() protoreflect.Message {
mi := &file_signers_proto_msgTypes[8]
mi := &file_signers_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -2282,7 +2283,7 @@ func (x *RepeatedNestedSigner_Inner) ProtoReflect() protoreflect.Message {
}
func (x *RepeatedNestedSigner_Inner) slowProtoReflect() protoreflect.Message {
mi := &file_signers_proto_msgTypes[9]
mi := &file_signers_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -3183,7 +3184,7 @@ func (x *NestedRepeatedSigner_Inner) ProtoReflect() protoreflect.Message {
}
func (x *NestedRepeatedSigner_Inner) slowProtoReflect() protoreflect.Message {
mi := &file_signers_proto_msgTypes[10]
mi := &file_signers_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -4157,7 +4158,7 @@ func (x *RepeatedNestedRepeatedSigner_Inner) ProtoReflect() protoreflect.Message
}
func (x *RepeatedNestedRepeatedSigner_Inner) slowProtoReflect() protoreflect.Message {
mi := &file_signers_proto_msgTypes[11]
mi := &file_signers_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -5415,6 +5416,426 @@ func (x *fastReflection_NoSignerOption) ProtoMethods() *protoiface.Methods {
}
}
var (
md_ValidatorSigner protoreflect.MessageDescriptor
fd_ValidatorSigner_signer protoreflect.FieldDescriptor
)
func init() {
file_signers_proto_init()
md_ValidatorSigner = File_signers_proto.Messages().ByName("ValidatorSigner")
fd_ValidatorSigner_signer = md_ValidatorSigner.Fields().ByName("signer")
}
var _ protoreflect.Message = (*fastReflection_ValidatorSigner)(nil)
type fastReflection_ValidatorSigner ValidatorSigner
func (x *ValidatorSigner) ProtoReflect() protoreflect.Message {
return (*fastReflection_ValidatorSigner)(x)
}
func (x *ValidatorSigner) slowProtoReflect() protoreflect.Message {
mi := &file_signers_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
var _fastReflection_ValidatorSigner_messageType fastReflection_ValidatorSigner_messageType
var _ protoreflect.MessageType = fastReflection_ValidatorSigner_messageType{}
type fastReflection_ValidatorSigner_messageType struct{}
func (x fastReflection_ValidatorSigner_messageType) Zero() protoreflect.Message {
return (*fastReflection_ValidatorSigner)(nil)
}
func (x fastReflection_ValidatorSigner_messageType) New() protoreflect.Message {
return new(fastReflection_ValidatorSigner)
}
func (x fastReflection_ValidatorSigner_messageType) Descriptor() protoreflect.MessageDescriptor {
return md_ValidatorSigner
}
// Descriptor returns message descriptor, which contains only the protobuf
// type information for the message.
func (x *fastReflection_ValidatorSigner) Descriptor() protoreflect.MessageDescriptor {
return md_ValidatorSigner
}
// Type returns the message type, which encapsulates both Go and protobuf
// type information. If the Go type information is not needed,
// it is recommended that the message descriptor be used instead.
func (x *fastReflection_ValidatorSigner) Type() protoreflect.MessageType {
return _fastReflection_ValidatorSigner_messageType
}
// New returns a newly allocated and mutable empty message.
func (x *fastReflection_ValidatorSigner) New() protoreflect.Message {
return new(fastReflection_ValidatorSigner)
}
// Interface unwraps the message reflection interface and
// returns the underlying ProtoMessage interface.
func (x *fastReflection_ValidatorSigner) Interface() protoreflect.ProtoMessage {
return (*ValidatorSigner)(x)
}
// Range iterates over every populated field in an undefined order,
// calling f for each field descriptor and value encountered.
// Range returns immediately if f returns false.
// While iterating, mutating operations may only be performed
// on the current field descriptor.
func (x *fastReflection_ValidatorSigner) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
if x.Signer != "" {
value := protoreflect.ValueOfString(x.Signer)
if !f(fd_ValidatorSigner_signer, value) {
return
}
}
}
// Has reports whether a field is populated.
//
// Some fields have the property of nullability where it is possible to
// distinguish between the default value of a field and whether the field
// was explicitly populated with the default value. Singular message fields,
// member fields of a oneof, and proto2 scalar fields are nullable. Such
// fields are populated only if explicitly set.
//
// In other cases (aside from the nullable cases above),
// a proto3 scalar field is populated if it contains a non-zero value, and
// a repeated field is populated if it is non-empty.
func (x *fastReflection_ValidatorSigner) Has(fd protoreflect.FieldDescriptor) bool {
switch fd.FullName() {
case "ValidatorSigner.signer":
return x.Signer != ""
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: ValidatorSigner"))
}
panic(fmt.Errorf("message ValidatorSigner does not contain field %s", fd.FullName()))
}
}
// Clear clears the field such that a subsequent Has call reports false.
//
// Clearing an extension field clears both the extension type and value
// associated with the given field number.
//
// Clear is a mutating operation and unsafe for concurrent use.
func (x *fastReflection_ValidatorSigner) Clear(fd protoreflect.FieldDescriptor) {
switch fd.FullName() {
case "ValidatorSigner.signer":
x.Signer = ""
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: ValidatorSigner"))
}
panic(fmt.Errorf("message ValidatorSigner does not contain field %s", fd.FullName()))
}
}
// Get retrieves the value for a field.
//
// For unpopulated scalars, it returns the default value, where
// the default value of a bytes scalar is guaranteed to be a copy.
// For unpopulated composite types, it returns an empty, read-only view
// of the value; to obtain a mutable reference, use Mutable.
func (x *fastReflection_ValidatorSigner) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value {
switch descriptor.FullName() {
case "ValidatorSigner.signer":
value := x.Signer
return protoreflect.ValueOfString(value)
default:
if descriptor.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: ValidatorSigner"))
}
panic(fmt.Errorf("message ValidatorSigner does not contain field %s", descriptor.FullName()))
}
}
// Set stores the value for a field.
//
// For a field belonging to a oneof, it implicitly clears any other field
// that may be currently set within the same oneof.
// For extension fields, it implicitly stores the provided ExtensionType.
// When setting a composite type, it is unspecified whether the stored value
// aliases the source's memory in any way. If the composite value is an
// empty, read-only value, then it panics.
//
// Set is a mutating operation and unsafe for concurrent use.
func (x *fastReflection_ValidatorSigner) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) {
switch fd.FullName() {
case "ValidatorSigner.signer":
x.Signer = value.Interface().(string)
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: ValidatorSigner"))
}
panic(fmt.Errorf("message ValidatorSigner does not contain field %s", fd.FullName()))
}
}
// Mutable returns a mutable reference to a composite type.
//
// If the field is unpopulated, it may allocate a composite value.
// For a field belonging to a oneof, it implicitly clears any other field
// that may be currently set within the same oneof.
// For extension fields, it implicitly stores the provided ExtensionType
// if not already stored.
// It panics if the field does not contain a composite type.
//
// Mutable is a mutating operation and unsafe for concurrent use.
func (x *fastReflection_ValidatorSigner) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
switch fd.FullName() {
case "ValidatorSigner.signer":
panic(fmt.Errorf("field signer of message ValidatorSigner is not mutable"))
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: ValidatorSigner"))
}
panic(fmt.Errorf("message ValidatorSigner does not contain field %s", fd.FullName()))
}
}
// NewField returns a new value that is assignable to the field
// for the given descriptor. For scalars, this returns the default value.
// For lists, maps, and messages, this returns a new, empty, mutable value.
func (x *fastReflection_ValidatorSigner) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value {
switch fd.FullName() {
case "ValidatorSigner.signer":
return protoreflect.ValueOfString("")
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: ValidatorSigner"))
}
panic(fmt.Errorf("message ValidatorSigner does not contain field %s", fd.FullName()))
}
}
// WhichOneof reports which field within the oneof is populated,
// returning nil if none are populated.
// It panics if the oneof descriptor does not belong to this message.
func (x *fastReflection_ValidatorSigner) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor {
switch d.FullName() {
default:
panic(fmt.Errorf("%s is not a oneof field in ValidatorSigner", d.FullName()))
}
panic("unreachable")
}
// GetUnknown retrieves the entire list of unknown fields.
// The caller may only mutate the contents of the RawFields
// if the mutated bytes are stored back into the message with SetUnknown.
func (x *fastReflection_ValidatorSigner) GetUnknown() protoreflect.RawFields {
return x.unknownFields
}
// SetUnknown stores an entire list of unknown fields.
// The raw fields must be syntactically valid according to the wire format.
// An implementation may panic if this is not the case.
// Once stored, the caller must not mutate the content of the RawFields.
// An empty RawFields may be passed to clear the fields.
//
// SetUnknown is a mutating operation and unsafe for concurrent use.
func (x *fastReflection_ValidatorSigner) SetUnknown(fields protoreflect.RawFields) {
x.unknownFields = fields
}
// IsValid reports whether the message is valid.
//
// An invalid message is an empty, read-only value.
//
// An invalid message often corresponds to a nil pointer of the concrete
// message type, but the details are implementation dependent.
// Validity is not part of the protobuf data model, and may not
// be preserved in marshaling or other operations.
func (x *fastReflection_ValidatorSigner) IsValid() bool {
return x != nil
}
// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations.
// This method may return nil.
//
// The returned methods type is identical to
// "google.golang.org/protobuf/runtime/protoiface".Methods.
// Consult the protoiface package documentation for details.
func (x *fastReflection_ValidatorSigner) ProtoMethods() *protoiface.Methods {
size := func(input protoiface.SizeInput) protoiface.SizeOutput {
x := input.Message.Interface().(*ValidatorSigner)
if x == nil {
return protoiface.SizeOutput{
NoUnkeyedLiterals: input.NoUnkeyedLiterals,
Size: 0,
}
}
options := runtime.SizeInputToOptions(input)
_ = options
var n int
var l int
_ = l
l = len(x.Signer)
if l > 0 {
n += 1 + l + runtime.Sov(uint64(l))
}
if x.unknownFields != nil {
n += len(x.unknownFields)
}
return protoiface.SizeOutput{
NoUnkeyedLiterals: input.NoUnkeyedLiterals,
Size: n,
}
}
marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) {
x := input.Message.Interface().(*ValidatorSigner)
if x == nil {
return protoiface.MarshalOutput{
NoUnkeyedLiterals: input.NoUnkeyedLiterals,
Buf: input.Buf,
}, nil
}
options := runtime.MarshalInputToOptions(input)
_ = options
size := options.Size(x)
dAtA := make([]byte, size)
i := len(dAtA)
_ = i
var l int
_ = l
if x.unknownFields != nil {
i -= len(x.unknownFields)
copy(dAtA[i:], x.unknownFields)
}
if len(x.Signer) > 0 {
i -= len(x.Signer)
copy(dAtA[i:], x.Signer)
i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Signer)))
i--
dAtA[i] = 0xa
}
if input.Buf != nil {
input.Buf = append(input.Buf, dAtA...)
} else {
input.Buf = dAtA
}
return protoiface.MarshalOutput{
NoUnkeyedLiterals: input.NoUnkeyedLiterals,
Buf: input.Buf,
}, nil
}
unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) {
x := input.Message.Interface().(*ValidatorSigner)
if x == nil {
return protoiface.UnmarshalOutput{
NoUnkeyedLiterals: input.NoUnkeyedLiterals,
Flags: input.Flags,
}, nil
}
options := runtime.UnmarshalInputToOptions(input)
_ = options
dAtA := input.Buf
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow
}
if iNdEx >= l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: ValidatorSigner: wiretype end group for non-group")
}
if fieldNum <= 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: ValidatorSigner: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow
}
if iNdEx >= l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
}
if postIndex > l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
x.Signer = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := runtime.Skip(dAtA[iNdEx:])
if err != nil {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
}
if (iNdEx + skippy) > l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
if !options.DiscardUnknown {
x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...)
}
iNdEx += skippy
}
}
if iNdEx > l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil
}
return &protoiface.Methods{
NoUnkeyedLiterals: struct{}{},
Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown,
Size: size,
Marshal: marshal,
Unmarshal: unmarshal,
Merge: nil,
CheckInitialized: nil,
}
}
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.0
@ -5708,6 +6129,41 @@ func (x *NoSignerOption) GetSigner() []byte {
return nil
}
type ValidatorSigner struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"`
}
func (x *ValidatorSigner) Reset() {
*x = ValidatorSigner{}
if protoimpl.UnsafeEnabled {
mi := &file_signers_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ValidatorSigner) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ValidatorSigner) ProtoMessage() {}
// Deprecated: Use ValidatorSigner.ProtoReflect.Descriptor instead.
func (*ValidatorSigner) Descriptor() ([]byte, []int) {
return file_signers_proto_rawDescGZIP(), []int{8}
}
func (x *ValidatorSigner) GetSigner() string {
if x != nil {
return x.Signer
}
return ""
}
type NestedSigner_Inner struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -5719,7 +6175,7 @@ type NestedSigner_Inner struct {
func (x *NestedSigner_Inner) Reset() {
*x = NestedSigner_Inner{}
if protoimpl.UnsafeEnabled {
mi := &file_signers_proto_msgTypes[8]
mi := &file_signers_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -5754,7 +6210,7 @@ type RepeatedNestedSigner_Inner struct {
func (x *RepeatedNestedSigner_Inner) Reset() {
*x = RepeatedNestedSigner_Inner{}
if protoimpl.UnsafeEnabled {
mi := &file_signers_proto_msgTypes[9]
mi := &file_signers_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -5789,7 +6245,7 @@ type NestedRepeatedSigner_Inner struct {
func (x *NestedRepeatedSigner_Inner) Reset() {
*x = NestedRepeatedSigner_Inner{}
if protoimpl.UnsafeEnabled {
mi := &file_signers_proto_msgTypes[10]
mi := &file_signers_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -5824,7 +6280,7 @@ type RepeatedNestedRepeatedSigner_Inner struct {
func (x *RepeatedNestedRepeatedSigner_Inner) Reset() {
*x = RepeatedNestedRepeatedSigner_Inner{}
if protoimpl.UnsafeEnabled {
mi := &file_signers_proto_msgTypes[11]
mi := &file_signers_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -5853,57 +6309,65 @@ var File_signers_proto protoreflect.FileDescriptor
var file_signers_proto_rawDesc = []byte{
0x0a, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
0x17, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x73, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x6d,
0x73, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x33, 0x0a, 0x0c, 0x53, 0x69, 0x6d, 0x70,
0x6c, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e,
0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72,
0x3a, 0x0b, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x22, 0x35, 0x0a,
0x0e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12,
0x73, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73,
0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0x33, 0x0a, 0x0c, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x53, 0x69, 0x67,
0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x3a, 0x0b, 0x82, 0xe7, 0xb0,
0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x22, 0x35, 0x0a, 0x0e, 0x52, 0x65, 0x70, 0x65,
0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69,
0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e,
0x65, 0x72, 0x3a, 0x0b, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x22,
0x73, 0x0a, 0x0c, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12,
0x29, 0x0a, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13,
0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x2e, 0x49, 0x6e,
0x6e, 0x65, 0x72, 0x52, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x1a, 0x2c, 0x0a, 0x05, 0x49, 0x6e,
0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x3a, 0x0b, 0x82, 0xe7, 0xb0,
0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x69,
0x6e, 0x6e, 0x65, 0x72, 0x22, 0x83, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65,
0x64, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x31, 0x0a,
0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x52,
0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67,
0x6e, 0x65, 0x72, 0x2e, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72,
0x1a, 0x2c, 0x0a, 0x05, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69, 0x67,
0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65,
0x72, 0x3a, 0x0b, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x3a, 0x0a,
0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x22, 0x83, 0x01, 0x0a, 0x14, 0x4e,
0x65, 0x73, 0x74, 0x65, 0x64, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67,
0x6e, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x52, 0x65, 0x70, 0x65, 0x61,
0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x2e, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x52,
0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x1a, 0x2c, 0x0a, 0x05, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x12,
0x16, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52,
0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x3a, 0x0b, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69,
0x67, 0x6e, 0x65, 0x72, 0x22, 0x73, 0x0a, 0x0c, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x53, 0x69,
0x67, 0x6e, 0x65, 0x72, 0x12, 0x29, 0x0a, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e,
0x65, 0x72, 0x2e, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x1a,
0x2c, 0x0a, 0x05, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e,
0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72,
0x3a, 0x0b, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x3a, 0x0a, 0x82,
0xe7, 0xb0, 0x2a, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x22, 0x83, 0x01, 0x0a, 0x14, 0x52, 0x65,
0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e,
0x65, 0x72, 0x12, 0x31, 0x0a, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x1b, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x65, 0x73, 0x74,
0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x2e, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x05,
0x69, 0x6e, 0x6e, 0x65, 0x72, 0x1a, 0x2c, 0x0a, 0x05, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x16,
0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x3a, 0x0b, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67,
0x6e, 0x65, 0x72, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x22,
0x83, 0x01, 0x0a, 0x14, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74,
0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x05, 0x69, 0x6e, 0x6e, 0x65,
0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64,
0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x2e, 0x49,
0x6e, 0x6e, 0x65, 0x72, 0x52, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x1a, 0x2c, 0x0a, 0x05, 0x49,
0x6e, 0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01,
0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x3a, 0x0b, 0x82, 0xe7,
0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05,
0x69, 0x6e, 0x6e, 0x65, 0x72, 0x22, 0x93, 0x01, 0x0a, 0x1c, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74,
0x65, 0x64, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64,
0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x18,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64,
0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69,
0x67, 0x6e, 0x65, 0x72, 0x2e, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x05, 0x69, 0x6e, 0x6e, 0x65,
0x72, 0x1a, 0x2c, 0x0a, 0x05, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69,
0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e,
0x65, 0x72, 0x3a, 0x0b, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x3a,
0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x22, 0x30, 0x0a, 0x09, 0x42,
0x61, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e,
0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72,
0x3a, 0x0b, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x22, 0x28, 0x0a,
0x0e, 0x4e, 0x6f, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12,
0x16, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52,
0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x42, 0x3b, 0x42, 0x0c, 0x53, 0x69, 0x67, 0x6e, 0x65,
0x72, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x29, 0x63, 0x6f, 0x73, 0x6d, 0x6f,
0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x78, 0x2f, 0x74, 0x78, 0x2f, 0x74, 0x65, 0x78,
0x74, 0x75, 0x61, 0x6c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65,
0x73, 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x67, 0x6e, 0x65, 0x72, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72,
0x22, 0x93, 0x01, 0x0a, 0x1c, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x65, 0x73,
0x74, 0x65, 0x64, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x65,
0x72, 0x12, 0x39, 0x0a, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x23, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x65, 0x73, 0x74, 0x65,
0x64, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x2e,
0x49, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x1a, 0x2c, 0x0a, 0x05,
0x49, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18,
0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x3a, 0x0b, 0x82,
0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a,
0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x22, 0x30, 0x0a, 0x09, 0x42, 0x61, 0x64, 0x53, 0x69, 0x67,
0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x3a, 0x0b, 0x82, 0xe7, 0xb0,
0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x22, 0x28, 0x0a, 0x0e, 0x4e, 0x6f, 0x53, 0x69,
0x67, 0x6e, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69,
0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e,
0x65, 0x72, 0x22, 0x59, 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53,
0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x21, 0xd2, 0xb4, 0x2d, 0x1d, 0x63, 0x6f, 0x73, 0x6d, 0x6f,
0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65,
0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72,
0x3a, 0x0b, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x42, 0x3b, 0x42,
0x0c, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a,
0x29, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x78, 0x2f,
0x74, 0x78, 0x2f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x61, 0x6c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
var (
@ -5918,7 +6382,7 @@ func file_signers_proto_rawDescGZIP() []byte {
return file_signers_proto_rawDescData
}
var file_signers_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
var file_signers_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
var file_signers_proto_goTypes = []interface{}{
(*SimpleSigner)(nil), // 0: SimpleSigner
(*RepeatedSigner)(nil), // 1: RepeatedSigner
@ -5928,16 +6392,17 @@ var file_signers_proto_goTypes = []interface{}{
(*RepeatedNestedRepeatedSigner)(nil), // 5: RepeatedNestedRepeatedSigner
(*BadSigner)(nil), // 6: BadSigner
(*NoSignerOption)(nil), // 7: NoSignerOption
(*NestedSigner_Inner)(nil), // 8: NestedSigner.Inner
(*RepeatedNestedSigner_Inner)(nil), // 9: RepeatedNestedSigner.Inner
(*NestedRepeatedSigner_Inner)(nil), // 10: NestedRepeatedSigner.Inner
(*RepeatedNestedRepeatedSigner_Inner)(nil), // 11: RepeatedNestedRepeatedSigner.Inner
(*ValidatorSigner)(nil), // 8: ValidatorSigner
(*NestedSigner_Inner)(nil), // 9: NestedSigner.Inner
(*RepeatedNestedSigner_Inner)(nil), // 10: RepeatedNestedSigner.Inner
(*NestedRepeatedSigner_Inner)(nil), // 11: NestedRepeatedSigner.Inner
(*RepeatedNestedRepeatedSigner_Inner)(nil), // 12: RepeatedNestedRepeatedSigner.Inner
}
var file_signers_proto_depIdxs = []int32{
8, // 0: NestedSigner.inner:type_name -> NestedSigner.Inner
9, // 1: RepeatedNestedSigner.inner:type_name -> RepeatedNestedSigner.Inner
10, // 2: NestedRepeatedSigner.inner:type_name -> NestedRepeatedSigner.Inner
11, // 3: RepeatedNestedRepeatedSigner.inner:type_name -> RepeatedNestedRepeatedSigner.Inner
9, // 0: NestedSigner.inner:type_name -> NestedSigner.Inner
10, // 1: RepeatedNestedSigner.inner:type_name -> RepeatedNestedSigner.Inner
11, // 2: NestedRepeatedSigner.inner:type_name -> NestedRepeatedSigner.Inner
12, // 3: RepeatedNestedRepeatedSigner.inner:type_name -> RepeatedNestedRepeatedSigner.Inner
4, // [4:4] is the sub-list for method output_type
4, // [4:4] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
@ -6048,7 +6513,7 @@ func file_signers_proto_init() {
}
}
file_signers_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NestedSigner_Inner); i {
switch v := v.(*ValidatorSigner); i {
case 0:
return &v.state
case 1:
@ -6060,7 +6525,7 @@ func file_signers_proto_init() {
}
}
file_signers_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RepeatedNestedSigner_Inner); i {
switch v := v.(*NestedSigner_Inner); i {
case 0:
return &v.state
case 1:
@ -6072,7 +6537,7 @@ func file_signers_proto_init() {
}
}
file_signers_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NestedRepeatedSigner_Inner); i {
switch v := v.(*RepeatedNestedSigner_Inner); i {
case 0:
return &v.state
case 1:
@ -6084,6 +6549,18 @@ func file_signers_proto_init() {
}
}
file_signers_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NestedRepeatedSigner_Inner); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_signers_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RepeatedNestedRepeatedSigner_Inner); i {
case 0:
return &v.state
@ -6102,7 +6579,7 @@ func file_signers_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_signers_proto_rawDesc,
NumEnums: 0,
NumMessages: 12,
NumMessages: 13,
NumExtensions: 0,
NumServices: 0,
},

320
x/tx/signing/context.go Normal file
View File

@ -0,0 +1,320 @@
package signing
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"
)
// Context is a context for retrieving the list of signers from a
// message where signers are specified by the cosmos.msg.v1.signer protobuf
// option. It also contains the ProtoFileResolver and address.Codec's used
// for resolving message descriptors and converting addresses.
type Context struct {
fileResolver ProtoFileResolver
typeResolver protoregistry.MessageTypeResolver
addressCodec address.Codec
validatorAddressCodec address.Codec
getSignersFuncs map[protoreflect.FullName]getSignersFunc
}
// Options are options for creating Context which will be used for signing operations.
type Options struct {
// FileResolver is the protobuf file resolver to use for resolving message descriptors.
// If it is nil, the global protobuf registry will be used.
FileResolver ProtoFileResolver
// TypeResolver is the protobuf type resolver to use for resolving message types.
TypeResolver protoregistry.MessageTypeResolver
// AddressCodec is the codec for converting addresses between strings and bytes.
AddressCodec address.Codec
// ValidatorAddressCodec is the codec for converting validator addresses between strings and bytes.
ValidatorAddressCodec address.Codec
}
// ProtoFileResolver is a protodesc.Resolver that also allows iterating over all
// files descriptors. It is a subset of the methods supported by protoregistry.Files.
type ProtoFileResolver interface {
protodesc.Resolver
RangeFiles(func(protoreflect.FileDescriptor) bool)
}
// NewContext creates a new Context using the provided options.
func NewContext(options Options) (*Context, error) {
protoFiles := options.FileResolver
if protoFiles == nil {
protoFiles = protoregistry.GlobalFiles
}
protoTypes := options.TypeResolver
if protoTypes == nil {
protoTypes = protoregistry.GlobalTypes
}
if options.AddressCodec == nil {
return nil, errors.New("address codec is required")
}
if options.ValidatorAddressCodec == nil {
return nil, errors.New("validator address codec is required")
}
c := &Context{
fileResolver: protoFiles,
typeResolver: protoTypes,
addressCodec: options.AddressCodec,
validatorAddressCodec: options.ValidatorAddressCodec,
getSignersFuncs: map[protoreflect.FullName]getSignersFunc{},
}
return c, c.init()
}
type getSignersFunc func(proto.Message) ([][]byte, error)
func getSignersFieldNames(descriptor protoreflect.MessageDescriptor) ([]string, error) {
signersFields := proto.GetExtension(descriptor.Options(), msgv1.E_Signer).([]string)
if len(signersFields) == 0 {
return nil, fmt.Errorf("no cosmos.msg.v1.signer option found for message %s", descriptor.FullName())
}
return signersFields, nil
}
// init 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 {
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" {
continue
}
for j := 0; j < sd.Methods().Len(); j++ {
md := sd.Methods().Get(j).Input()
msg := dynamicpb.NewMessage(md)
_, err := c.GetSigners(msg)
if err != nil {
errs = append(errs, err)
}
}
}
return true
})
return errors.Join(errs...)
}
func (c *Context) makeGetSignersFunc(descriptor protoreflect.MessageDescriptor) (getSignersFunc, error) {
signersFields, err := getSignersFieldNames(descriptor)
if err != nil {
return nil, err
}
fieldGetters := make([]func(proto.Message, [][]byte) ([][]byte, error), len(signersFields))
for i, fieldName := range signersFields {
field := descriptor.Fields().ByName(protoreflect.Name(fieldName))
if field == nil {
return nil, fmt.Errorf("field %s not found in message %s", fieldName, descriptor.FullName())
}
if field.IsMap() || field.HasOptionalKeyword() {
return nil, fmt.Errorf("cosmos.msg.v1.signer field %s in message %s must not be a map or optional", fieldName, descriptor.FullName())
}
switch field.Kind() {
case protoreflect.StringKind:
addrCdc := c.getAddressCodec(field)
if field.IsList() {
fieldGetters[i] = func(msg proto.Message, arr [][]byte) ([][]byte, error) {
signers := msg.ProtoReflect().Get(field).List()
n := signers.Len()
for i := 0; i < n; i++ {
addrStr := signers.Get(i).String()
addrBz, err := addrCdc.StringToBytes(addrStr)
if err != nil {
return nil, err
}
arr = append(arr, addrBz)
}
return arr, nil
}
} else {
fieldGetters[i] = func(msg proto.Message, arr [][]byte) ([][]byte, error) {
addrStr := msg.ProtoReflect().Get(field).String()
addrBz, err := addrCdc.StringToBytes(addrStr)
if err != nil {
return nil, err
}
return append(arr, addrBz), nil
}
}
case protoreflect.MessageKind:
isList := field.IsList()
nestedMessage := field.Message()
nestedSignersFields, err := getSignersFieldNames(nestedMessage)
if err != nil {
return nil, err
}
if len(nestedSignersFields) != 1 {
return nil, fmt.Errorf("nested cosmos.msg.v1.signer option in message %s must contain only one value", nestedMessage.FullName())
}
nestedFieldName := nestedSignersFields[0]
nestedField := nestedMessage.Fields().ByName(protoreflect.Name(nestedFieldName))
nestedIsList := nestedField.IsList()
if nestedField == nil {
return nil, fmt.Errorf("field %s not found in message %s", nestedFieldName, nestedMessage.FullName())
}
if nestedField.Kind() != protoreflect.StringKind || nestedField.IsMap() || nestedField.HasOptionalKeyword() {
return nil, fmt.Errorf("nested signer field %s in message %s must be a simple string", nestedFieldName, nestedMessage.FullName())
}
addrCdc := c.getAddressCodec(nestedField)
if isList {
if nestedIsList {
fieldGetters[i] = func(msg proto.Message, arr [][]byte) ([][]byte, error) {
msgs := msg.ProtoReflect().Get(field).List()
m := msgs.Len()
for i := 0; i < m; i++ {
signers := msgs.Get(i).Message().Get(nestedField).List()
n := signers.Len()
for j := 0; j < n; j++ {
addrStr := signers.Get(j).String()
addrBz, err := addrCdc.StringToBytes(addrStr)
if err != nil {
return nil, err
}
arr = append(arr, addrBz)
}
}
return arr, nil
}
} else {
fieldGetters[i] = func(msg proto.Message, arr [][]byte) ([][]byte, error) {
msgs := msg.ProtoReflect().Get(field).List()
m := msgs.Len()
for i := 0; i < m; i++ {
addrStr := msgs.Get(i).Message().Get(nestedField).String()
addrBz, err := addrCdc.StringToBytes(addrStr)
if err != nil {
return nil, err
}
arr = append(arr, addrBz)
}
return arr, nil
}
}
} else {
if nestedIsList {
fieldGetters[i] = func(msg proto.Message, arr [][]byte) ([][]byte, error) {
nestedMsg := msg.ProtoReflect().Get(field).Message()
signers := nestedMsg.Get(nestedField).List()
n := signers.Len()
for j := 0; j < n; j++ {
addrStr := signers.Get(j).String()
addrBz, err := addrCdc.StringToBytes(addrStr)
if err != nil {
return nil, err
}
arr = append(arr, addrBz)
}
return arr, nil
}
} else {
fieldGetters[i] = func(msg proto.Message, arr [][]byte) ([][]byte, error) {
addrStr := msg.ProtoReflect().Get(field).Message().Get(nestedField).String()
addrBz, err := addrCdc.StringToBytes(addrStr)
if err != nil {
return nil, err
}
return append(arr, addrBz), nil
}
}
}
default:
return nil, fmt.Errorf("unexpected field type %s for field %s in message %s", field.Kind(), fieldName, descriptor.FullName())
}
}
return func(message proto.Message) ([][]byte, error) {
var signers [][]byte
for _, getter := range fieldGetters {
signers, err = getter(message, signers)
if err != nil {
return nil, err
}
}
return signers, nil
}, nil
}
func (c *Context) getAddressCodec(field protoreflect.FieldDescriptor) address.Codec {
scalarOpt := proto.GetExtension(field.Options(), cosmos_proto.E_Scalar)
addrCdc := c.addressCodec
if scalarOpt != nil {
if scalarOpt.(string) == "cosmos.ValidatorAddressString" {
addrCdc = c.validatorAddressCodec
}
}
return addrCdc
}
// GetSigners returns the signers for a given message.
func (c *Context) GetSigners(msg proto.Message) ([][]byte, error) {
messageDescriptor := msg.ProtoReflect().Descriptor()
f, ok := c.getSignersFuncs[messageDescriptor.FullName()]
if !ok {
var err error
f, err = c.makeGetSignersFunc(messageDescriptor)
if err != nil {
return nil, err
}
c.getSignersFuncs[messageDescriptor.FullName()] = f
}
return f(msg)
}
// AddressCodec returns the address codec used by the context.
func (c *Context) AddressCodec() address.Codec {
return c.addressCodec
}
// ValidatorAddressCodec returns the validator address codec used by the context.
func (c *Context) ValidatorAddressCodec() address.Codec {
return c.validatorAddressCodec
}
// FileResolver returns the proto file resolver used by the context.
func (c *Context) FileResolver() ProtoFileResolver {
return c.fileResolver
}
func (c *Context) TypeResolver() protoregistry.MessageTypeResolver {
return c.typeResolver
}

View File

@ -0,0 +1,170 @@
package signing
import (
"encoding/hex"
"strings"
"testing"
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
groupv1 "cosmossdk.io/api/cosmos/group/v1"
"cosmossdk.io/core/address"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"
"cosmossdk.io/x/tx/internal/testpb"
)
func TestGetSigners(t *testing.T) {
ctx, err := NewContext(Options{
AddressCodec: dummyAddressCodec{},
ValidatorAddressCodec: dummyValidatorAddressCodec{},
})
require.NoError(t, err)
tests := []struct {
name string
msg proto.Message
want [][]byte
wantErr bool
}{
{
name: "MsgSend",
msg: &bankv1beta1.MsgSend{
FromAddress: hex.EncodeToString([]byte("foo")),
},
want: [][]byte{[]byte("foo")},
},
{
name: "MsgMultiSend",
msg: &bankv1beta1.MsgMultiSend{
Inputs: []*bankv1beta1.Input{
{Address: hex.EncodeToString([]byte("foo"))},
{Address: hex.EncodeToString([]byte("bar"))},
},
},
want: [][]byte{[]byte("foo"), []byte("bar")},
},
{
name: "MsgSubmitProposal",
msg: &groupv1.MsgSubmitProposal{
Proposers: []string{
hex.EncodeToString([]byte("foo")),
hex.EncodeToString([]byte("bar")),
},
},
want: [][]byte{[]byte("foo"), []byte("bar")},
},
{
name: "simple",
msg: &testpb.SimpleSigner{Signer: hex.EncodeToString([]byte("foo"))},
want: [][]byte{[]byte("foo")},
},
{
name: "repeated",
msg: &testpb.RepeatedSigner{Signer: []string{
hex.EncodeToString([]byte("foo")),
hex.EncodeToString([]byte("bar")),
}},
want: [][]byte{[]byte("foo"), []byte("bar")},
},
{
name: "nested",
msg: &testpb.NestedSigner{Inner: &testpb.NestedSigner_Inner{Signer: hex.EncodeToString([]byte("foo"))}},
want: [][]byte{[]byte("foo")},
},
{
name: "nested repeated",
msg: &testpb.NestedRepeatedSigner{Inner: &testpb.NestedRepeatedSigner_Inner{Signer: []string{
hex.EncodeToString([]byte("foo")),
hex.EncodeToString([]byte("bar")),
}}},
want: [][]byte{[]byte("foo"), []byte("bar")},
},
{
name: "repeated nested",
msg: &testpb.RepeatedNestedSigner{Inner: []*testpb.RepeatedNestedSigner_Inner{
{Signer: hex.EncodeToString([]byte("foo"))},
{Signer: hex.EncodeToString([]byte("bar"))},
}},
want: [][]byte{[]byte("foo"), []byte("bar")},
},
{
name: "nested repeated",
msg: &testpb.NestedRepeatedSigner{Inner: &testpb.NestedRepeatedSigner_Inner{
Signer: []string{
hex.EncodeToString([]byte("foo")),
hex.EncodeToString([]byte("bar")),
},
}},
want: [][]byte{[]byte("foo"), []byte("bar")},
},
{
name: "repeated nested repeated",
msg: &testpb.RepeatedNestedRepeatedSigner{Inner: []*testpb.RepeatedNestedRepeatedSigner_Inner{
{Signer: []string{
hex.EncodeToString([]byte("foo")),
hex.EncodeToString([]byte("bar")),
}},
{Signer: []string{
hex.EncodeToString([]byte("baz")),
hex.EncodeToString([]byte("bam")),
}},
{Signer: []string{
hex.EncodeToString([]byte("blah")),
}},
}},
want: [][]byte{[]byte("foo"), []byte("bar"), []byte("baz"), []byte("bam"), []byte("blah")},
},
{
name: "bad",
msg: &testpb.BadSigner{},
wantErr: true,
},
{
name: "no signer",
msg: &testpb.NoSignerOption{},
wantErr: true,
},
{
name: "validator signer",
msg: &testpb.ValidatorSigner{
Signer: "val" + hex.EncodeToString([]byte("foo")),
},
want: [][]byte{[]byte("foo")},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
signers, err := ctx.GetSigners(test.msg)
if test.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
require.Equal(t, test.want, signers)
})
}
}
type dummyAddressCodec struct{}
func (d dummyAddressCodec) StringToBytes(text string) ([]byte, error) {
return hex.DecodeString(text)
}
func (d dummyAddressCodec) BytesToString(bz []byte) (string, error) {
return hex.EncodeToString(bz), nil
}
var _ address.Codec = dummyAddressCodec{}
type dummyValidatorAddressCodec struct{}
func (d dummyValidatorAddressCodec) StringToBytes(text string) ([]byte, error) {
return hex.DecodeString(strings.TrimPrefix(text, "val"))
}
func (d dummyValidatorAddressCodec) BytesToString(bz []byte) (string, error) {
return "val" + hex.EncodeToString(bz), nil
}
var _ address.Codec = dummyValidatorAddressCodec{}

View File

@ -16,32 +16,30 @@ import (
// SignModeHandler is the SIGN_MODE_DIRECT_AUX implementation of signing.SignModeHandler.
type SignModeHandler struct {
signersContext *signing.GetSignersContext
signersContext *signing.Context
fileResolver signing.ProtoFileResolver
typeResolver protoregistry.MessageTypeResolver
}
// SignModeHandlerOptions are the options for the SignModeHandler.
type SignModeHandlerOptions struct {
// FileResolver is the protodesc.Resolver to use for resolving proto files when unpacking any messages.
FileResolver signing.ProtoFileResolver
// TypeResolver is the protoregistry.MessageTypeResolver to use for resolving proto types when unpacking any messages.
// TypeResolver is the protoregistry.MessageTypeResolver to use for resolving protobuf types when unpacking any messages.
TypeResolver protoregistry.MessageTypeResolver
// SignersContext is the signing.GetSignersContext to use for getting signers.
SignersContext *signing.GetSignersContext
// SignersContext is the signing.Context to use for getting signers.
SignersContext *signing.Context
}
// NewSignModeHandler returns a new SignModeHandler.
func NewSignModeHandler(options SignModeHandlerOptions) (SignModeHandler, error) {
h := SignModeHandler{}
if options.FileResolver == nil {
h.fileResolver = protoregistry.GlobalFiles
} else {
h.fileResolver = options.FileResolver
if options.SignersContext == nil {
return h, fmt.Errorf("signers context is required")
}
h.signersContext = options.SignersContext
h.fileResolver = h.signersContext.FileResolver()
if options.TypeResolver == nil {
h.typeResolver = protoregistry.GlobalTypes
@ -49,16 +47,6 @@ func NewSignModeHandler(options SignModeHandlerOptions) (SignModeHandler, error)
h.typeResolver = options.TypeResolver
}
if options.SignersContext == nil {
var err error
h.signersContext, err = signing.NewGetSignersContext(signing.GetSignersOptions{ProtoFiles: h.fileResolver})
if err != nil {
return h, err
}
} else {
h.signersContext = options.SignersContext
}
return h, nil
}
@ -71,18 +59,18 @@ func (h SignModeHandler) Mode() signingv1beta1.SignMode {
// getFirstSigner returns the first signer from the first message in the tx. It replicates behavior in
// https://github.com/cosmos/cosmos-sdk/blob/4a6a1e3cb8de459891cb0495052589673d14ef51/x/auth/tx/builder.go#L142
func (h SignModeHandler) getFirstSigner(txData signing.TxData) (string, error) {
func (h SignModeHandler) getFirstSigner(txData signing.TxData) ([]byte, error) {
if len(txData.Body.Messages) == 0 {
return "", fmt.Errorf("no signer found")
return nil, fmt.Errorf("no signer found")
}
msg, err := anyutil.Unpack(txData.Body.Messages[0], h.fileResolver, h.typeResolver)
if err != nil {
return "", err
return nil, err
}
signer, err := h.signersContext.GetSigners(msg)
if err != nil {
return "", err
return nil, err
}
return signer[0], nil
}
@ -97,7 +85,10 @@ func (h SignModeHandler) GetSignBytes(
if err != nil {
return nil, err
}
feePayer = fp
feePayer, err = h.signersContext.AddressCodec().BytesToString(fp)
if err != nil {
return nil, err
}
}
if feePayer == signerData.Address {
return nil, fmt.Errorf("fee payer %s cannot sign with %s: unauthorized",

View File

@ -2,9 +2,11 @@ package directaux_test
import (
"context"
"encoding/hex"
"fmt"
"testing"
"cosmossdk.io/core/address"
"github.com/cosmos/cosmos-proto/anyutil"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"
@ -15,6 +17,7 @@ import (
"cosmossdk.io/api/cosmos/crypto/secp256k1"
signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1"
txv1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1"
"cosmossdk.io/x/tx/signing"
"cosmossdk.io/x/tx/signing/directaux"
)
@ -83,7 +86,14 @@ func TestDirectAuxHandler(t *testing.T) {
AuthInfoBytes: authInfoBz,
BodyBytes: bodyBz,
}
modeHandler, err := directaux.NewSignModeHandler(directaux.SignModeHandlerOptions{})
signersCtx, err := signing.NewContext(signing.Options{
AddressCodec: dummyAddressCodec{},
ValidatorAddressCodec: dummyAddressCodec{},
})
require.NoError(t, err)
modeHandler, err := directaux.NewSignModeHandler(directaux.SignModeHandlerOptions{
SignersContext: signersCtx,
})
require.NoError(t, err)
t.Log("verify fee payer cannot use SIGN_MODE_DIRECT_AUX")
@ -143,3 +153,15 @@ func TestDirectAuxHandler(t *testing.T) {
require.NoError(t, err)
require.NotEqual(t, expectedSignBytes, signBytes)
}
type dummyAddressCodec struct{}
func (d dummyAddressCodec) StringToBytes(text string) ([]byte, error) {
return hex.DecodeString(text)
}
func (d dummyAddressCodec) BytesToString(bz []byte) (string, error) {
return hex.EncodeToString(bz), nil
}
var _ address.Codec = dummyAddressCodec{}

View File

@ -1,222 +0,0 @@
package signing
import (
"errors"
"fmt"
"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"
)
// GetSignersContext is a context for retrieving the list of signers from a
// message where signers are specified by the cosmos.msg.v1.signer protobuf
// option.
type GetSignersContext struct {
protoFiles ProtoFileResolver
getSignersFuncs map[protoreflect.FullName]getSignersFunc
}
// GetSignersOptions are options for creating GetSignersContext.
type GetSignersOptions struct {
// ProtoFiles are the protobuf files to use for resolving message descriptors.
// If it is nil, the global protobuf registry will be used.
ProtoFiles ProtoFileResolver
}
// ProtoFileResolver is a protodesc.Resolver that also allows iterating over all
// files descriptors. It is a subset of the methods supported by protoregistry.Files.
type ProtoFileResolver interface {
protodesc.Resolver
RangeFiles(func(protoreflect.FileDescriptor) bool)
}
// NewGetSignersContext creates a new GetSignersContext using the provided options.
func NewGetSignersContext(options GetSignersOptions) (*GetSignersContext, error) {
protoFiles := options.ProtoFiles
if protoFiles == nil {
protoFiles = protoregistry.GlobalFiles
}
c := &GetSignersContext{
protoFiles: protoFiles,
getSignersFuncs: map[protoreflect.FullName]getSignersFunc{},
}
return c, c.init()
}
type getSignersFunc func(proto.Message) []string
func getSignersFieldNames(descriptor protoreflect.MessageDescriptor) ([]string, error) {
signersFields := proto.GetExtension(descriptor.Options(), msgv1.E_Signer).([]string)
if len(signersFields) == 0 {
return nil, fmt.Errorf("no cosmos.msg.v1.signer option found for message %s", descriptor.FullName())
}
return signersFields, nil
}
// init 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 *GetSignersContext) init() error {
var errs []error
c.protoFiles.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" {
continue
}
for j := 0; j < sd.Methods().Len(); j++ {
md := sd.Methods().Get(j).Input()
msg := dynamicpb.NewMessage(md)
_, err := c.GetSigners(msg)
if err != nil {
errs = append(errs, err)
}
}
}
return true
})
return errors.Join(errs...)
}
func (*GetSignersContext) makeGetSignersFunc(descriptor protoreflect.MessageDescriptor) (getSignersFunc, error) {
signersFields, err := getSignersFieldNames(descriptor)
if err != nil {
return nil, err
}
fieldGetters := make([]func(proto.Message, []string) []string, len(signersFields))
for i, fieldName := range signersFields {
field := descriptor.Fields().ByName(protoreflect.Name(fieldName))
if field == nil {
return nil, fmt.Errorf("field %s not found in message %s", fieldName, descriptor.FullName())
}
if field.IsMap() || field.HasOptionalKeyword() {
return nil, fmt.Errorf("cosmos.msg.v1.signer field %s in message %s must not be a map or optional", fieldName, descriptor.FullName())
}
switch field.Kind() {
case protoreflect.StringKind:
if field.IsList() {
fieldGetters[i] = func(msg proto.Message, arr []string) []string {
signers := msg.ProtoReflect().Get(field).List()
n := signers.Len()
for i := 0; i < n; i++ {
arr = append(arr, signers.Get(i).String())
}
return arr
}
} else {
fieldGetters[i] = func(msg proto.Message, arr []string) []string {
return append(arr, msg.ProtoReflect().Get(field).String())
}
}
case protoreflect.MessageKind:
isList := field.IsList()
nestedMessage := field.Message()
nestedSignersFields, err := getSignersFieldNames(nestedMessage)
if err != nil {
return nil, err
}
if len(nestedSignersFields) != 1 {
return nil, fmt.Errorf("nested cosmos.msg.v1.signer option in message %s must contain only one value", nestedMessage.FullName())
}
nestedFieldName := nestedSignersFields[0]
nestedField := nestedMessage.Fields().ByName(protoreflect.Name(nestedFieldName))
nestedIsList := nestedField.IsList()
if nestedField == nil {
return nil, fmt.Errorf("field %s not found in message %s", nestedFieldName, nestedMessage.FullName())
}
if nestedField.Kind() != protoreflect.StringKind || nestedField.IsMap() || nestedField.HasOptionalKeyword() {
return nil, fmt.Errorf("nested signer field %s in message %s must be a simple string", nestedFieldName, nestedMessage.FullName())
}
if isList {
if nestedIsList {
fieldGetters[i] = func(msg proto.Message, arr []string) []string {
msgs := msg.ProtoReflect().Get(field).List()
m := msgs.Len()
for i := 0; i < m; i++ {
signers := msgs.Get(i).Message().Get(nestedField).List()
n := signers.Len()
for j := 0; j < n; j++ {
arr = append(arr, signers.Get(j).String())
}
}
return arr
}
} else {
fieldGetters[i] = func(msg proto.Message, arr []string) []string {
msgs := msg.ProtoReflect().Get(field).List()
m := msgs.Len()
for i := 0; i < m; i++ {
arr = append(arr, msgs.Get(i).Message().Get(nestedField).String())
}
return arr
}
}
} else {
if nestedIsList {
fieldGetters[i] = func(msg proto.Message, arr []string) []string {
nestedMsg := msg.ProtoReflect().Get(field).Message()
signers := nestedMsg.Get(nestedField).List()
n := signers.Len()
for j := 0; j < n; j++ {
arr = append(arr, signers.Get(j).String())
}
return arr
}
} else {
fieldGetters[i] = func(msg proto.Message, arr []string) []string {
return append(arr, msg.ProtoReflect().Get(field).Message().Get(nestedField).String())
}
}
}
default:
return nil, fmt.Errorf("unexpected field type %s for field %s in message %s", field.Kind(), fieldName, descriptor.FullName())
}
}
return func(message proto.Message) []string {
var signers []string
for _, getter := range fieldGetters {
signers = getter(message, signers)
}
return signers
}, nil
}
// GetSigners returns the signers for a given message.
func (c *GetSignersContext) GetSigners(msg proto.Message) ([]string, error) {
messageDescriptor := msg.ProtoReflect().Descriptor()
f, ok := c.getSignersFuncs[messageDescriptor.FullName()]
if !ok {
var err error
f, err = c.makeGetSignersFunc(messageDescriptor)
if err != nil {
return nil, err
}
c.getSignersFuncs[messageDescriptor.FullName()] = f
}
return f(msg), nil
}

View File

@ -1,113 +0,0 @@
package signing
import (
"testing"
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
groupv1 "cosmossdk.io/api/cosmos/group/v1"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"
"cosmossdk.io/x/tx/internal/testpb"
)
func TestGetSigners(t *testing.T) {
ctx, err := NewGetSignersContext(GetSignersOptions{})
require.NoError(t, err)
tests := []struct {
name string
msg proto.Message
want []string
wantErr bool
}{
{
name: "MsgSend",
msg: &bankv1beta1.MsgSend{
FromAddress: "foo",
},
want: []string{"foo"},
},
{
name: "MsgMultiSend",
msg: &bankv1beta1.MsgMultiSend{
Inputs: []*bankv1beta1.Input{
{Address: "foo"},
{Address: "bar"},
},
},
want: []string{"foo", "bar"},
},
{
name: "MsgSubmitProposal",
msg: &groupv1.MsgSubmitProposal{
Proposers: []string{"foo", "bar"},
},
want: []string{"foo", "bar"},
},
{
name: "simple",
msg: &testpb.SimpleSigner{Signer: "foo"},
want: []string{"foo"},
},
{
name: "repeated",
msg: &testpb.RepeatedSigner{Signer: []string{"foo", "bar"}},
want: []string{"foo", "bar"},
},
{
name: "nested",
msg: &testpb.NestedSigner{Inner: &testpb.NestedSigner_Inner{Signer: "foo"}},
want: []string{"foo"},
},
{
name: "nested repeated",
msg: &testpb.NestedRepeatedSigner{Inner: &testpb.NestedRepeatedSigner_Inner{Signer: []string{"foo", "bar"}}},
want: []string{"foo", "bar"},
},
{
name: "repeated nested",
msg: &testpb.RepeatedNestedSigner{Inner: []*testpb.RepeatedNestedSigner_Inner{
{Signer: "foo"},
{Signer: "bar"},
}},
want: []string{"foo", "bar"},
},
{
name: "nested repeated",
msg: &testpb.NestedRepeatedSigner{Inner: &testpb.NestedRepeatedSigner_Inner{
Signer: []string{"foo", "bar"},
}},
want: []string{"foo", "bar"},
},
{
name: "repeated nested repeated",
msg: &testpb.RepeatedNestedRepeatedSigner{Inner: []*testpb.RepeatedNestedRepeatedSigner_Inner{
{Signer: []string{"foo", "bar"}},
{Signer: []string{"baz", "bam"}},
{Signer: []string{"blah"}},
}},
want: []string{"foo", "bar", "baz", "bam", "blah"},
},
{
name: "bad",
msg: &testpb.BadSigner{},
wantErr: true,
},
{
name: "no signer",
msg: &testpb.NoSignerOption{},
wantErr: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
signers, err := ctx.GetSigners(test.msg)
if test.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
require.Equal(t, test.want, signers)
})
}
}