New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bug]: DefineCustomGetSigners is unusable. #20077
Comments
In the above example you need to run the pulsar code generator for The gogo types are converted to their wire format and dynamicpb when used in x/tx/signer code to convert from gogo -> a ProtoReflect enabled message. |
Having to create the pulsar code generation process just so that a custom I did figure out how to do it without the pulsar code, but it's pretty annoyingly convoluted as it has to rely on the proto reflection stuff instead of being able to just access the field like I would anywhere else in the code. Even with the pulsar code, though, I'm not sure it'd get any better. Instead of Then, in the actual Here's what it ended up looking like: func createThingGetSignersFunc(options *signing.Options, fieldName string) signing.GetSignersFunc {
return func(msgIn proto.Message) (addrs [][]byte, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic (recovered) getting %s.thing.%s as a signer: %v", proto.MessageName(msgIn), fieldName, r)
}
}()
msg := msgIn.ProtoReflect()
thingDesc := msg.Descriptor().Fields().ByName("thing")
if thingDesc == nil {
return nil, fmt.Errorf("no thing field found in %s", proto.MessageName(msgIn))
}
thing := msg.Get(thingDesc).Message()
fieldDesc := thing.Descriptor().Fields().ByName(protoreflect.Name(fieldName))
if fieldDesc == nil {
return nil, fmt.Errorf("no thing.%s field found in %s", fieldName, proto.MessageName(msgIn))
}
b32 := thing.Get(fieldDesc).Interface().(string)
addr, err := options.AddressCodec.StringToBytes(b32)
if err != nil {
return nil, fmt.Errorf("error decoding thing.%s address %q: %w", fieldName, b32, err)
}
return [][]byte{addr}, nil
}
}
func DefineCustomGetSigners(options *signing.Options) {
options.DefineCustomGetSigners(
proto.MessageName(protoadapt.MessageV2Of(&MsgStartThingRequest{})),
createThingGetSignersFunc(options, "addr1"))
options.DefineCustomGetSigners(
proto.MessageName(protoadapt.MessageV2Of(&MsgEndThingRequest{})),
createThingGetSignersFunc(options, "addr2"))
} That |
Feel free to close this bug. It'd be nice if this stuff were at least documented somewhere, though. Even better if I could just do |
Is there an existing issue for this?
What happened?
There is no way to use
DefineCustomGetSigners
on aMsg
.The
DefineCustomGetSigners
function uses theMessage
interface defined in"google.golang.org/protobuf/proto"
. That's an alias for theprotoreflect.ProtoMessage
interface, which just requires theProtoReflect() Message
method. But code generated from protos does not create that method on anything.All of the unit tests related to signing uses the pulsar stuff. But those things aren't what are actually used by the msg server. So there's no way to define a custom
GetSigners
method for anything that someone would be actually signing.Cosmos SDK Version
0.50.5
How to reproduce?
Here's the simplified situation I'm in where I need to define a custom
GetSigners
method.The signer of
MsgStartThingRequest
should bething.addr1
.The signer of
MsgEndThingRequest
should bething.addr2
.I can't use
option (cosmos.msg.v1.signer)
here because it no longer allows sub-fields. I.e., inMsgStartThingRequest
, I can't haveoption (cosmos.msg.v1.signer) = "thing.addr1"
, I can only haveoption (cosmos.msg.v1.signer) = "thing"
. I'd then have to put anoption (cosmos.msg.v1.signer)
in theThing
message, but it can't be hard-coded like that because the field that's the signer is different depending on whichMsg
theThing
is in. And there are othermessage
s that also have aThing
where neither should be a signer.In the go code, the msg server endpoint methods require the use of the
MsgStartThingRequest
struct as defined in the auto-generated go code that lives in the module code. ThoseMsg
structs (where we used to have to defineGetSigners()
), do not have aProtoReflect()
method, though. So it's impossible to define a customGetSigners
function on aMsg
required by an endpoint.Here's what the go code might look like to define the custom
GetSigners
forMsgStartThingRequest
:In that,
options
is acosmossdk.io/x/tx/signing.Options
, andproto
is thegoogle.golang.org/protobuf/proto
package.There are two compilation issues with that code.
proto.MessageName
takes in aprotoreflect.ProtoMessage
, butMsgStartThingRequest
doesn't have aProtoReflect()
method, so&MsgStartThingRequest{}
is an invalid argument for that function.proto.Message
type that the function takes in, is just an alias for thatprotoreflect.ProtoMessage
. SomsgIn
cannot be asserted as a(*MsgStartThingRequest)
because again,MsgStartThingRequest
does not have aProtoReflect()
method.The text was updated successfully, but these errors were encountered: