fix: deterministic protov2 marshal (#18403)

This commit is contained in:
Julien Robert 2023-11-07 17:22:57 +01:00 committed by GitHub
parent 1e4d1f955a
commit e2b71b7480
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 33 additions and 18 deletions

View File

@ -16,8 +16,9 @@ import (
)
var (
gogoType = reflect.TypeOf((*gogoproto.Message)(nil)).Elem()
protov2Type = reflect.TypeOf((*proto2.Message)(nil)).Elem()
gogoType = reflect.TypeOf((*gogoproto.Message)(nil)).Elem()
protov2Type = reflect.TypeOf((*proto2.Message)(nil)).Elem()
protov2MarshalOpts = proto2.MarshalOptions{Deterministic: true}
)
type Handler = func(ctx context.Context, request, response protoiface.MessageV1) error
@ -97,7 +98,7 @@ func makeProtoV2HybridHandler(prefMethod protoreflect.MethodDescriptor, cdc code
// the response is a protov2 message, so we cannot just return it.
// since the request came as gogoproto, we expect the response
// to also be gogoproto.
respBytes, err := proto2.Marshal(resp.(proto2.Message))
respBytes, err := protov2MarshalOpts.Marshal(resp.(proto2.Message))
if err != nil {
return err
}
@ -138,7 +139,7 @@ func makeGogoHybridHandler(prefMethod protoreflect.MethodDescriptor, cdc codec.B
switch m := inReq.(type) {
case proto2.Message:
// we need to marshal and unmarshal the request.
requestBytes, err := proto2.Marshal(m)
requestBytes, err := protov2MarshalOpts.Marshal(m)
if err != nil {
return err
}

View File

@ -104,7 +104,8 @@ type collValue2[T any, PT protoMessageV2[T]] struct {
}
func (c collValue2[T, PT]) Encode(value PT) ([]byte, error) {
return protov2.Marshal(value)
protov2MarshalOpts := protov2.MarshalOptions{Deterministic: true}
return protov2MarshalOpts.Marshal(value)
}
func (c collValue2[T, PT]) Decode(b []byte) (PT, error) {

View File

@ -345,7 +345,8 @@ type grpcProtoCodec struct {
func (g grpcProtoCodec) Marshal(v interface{}) ([]byte, error) {
switch m := v.(type) {
case proto.Message:
return proto.Marshal(m)
protov2MarshalOpts := proto.MarshalOptions{Deterministic: true}
return protov2MarshalOpts.Marshal(m)
case gogoproto.Message:
return g.cdc.Marshal(m)
default:

View File

@ -68,7 +68,8 @@ func NewAnyWithValue(v proto.Message) (*Any, error) {
err error
)
if msg, ok := v.(protov2.Message); ok {
bz, err = protov2.Marshal(msg)
protov2MarshalOpts := protov2.MarshalOptions{Deterministic: true}
bz, err = protov2MarshalOpts.Marshal(msg)
} else {
bz, err = proto.Marshal(v)
}
@ -109,7 +110,8 @@ func (any *Any) pack(x proto.Message) error {
err error
)
if msg, ok := x.(protov2.Message); ok {
bz, err = protov2.Marshal(msg)
protov2MarshalOpts := protov2.MarshalOptions{Deterministic: true}
bz, err = protov2MarshalOpts.Marshal(msg)
} else {
bz, err = proto.Marshal(x)
}

View File

@ -14,6 +14,8 @@ var (
errNoInitHandler = errors.New("no init handler")
errNoExecuteHandler = errors.New("account does not accept messages")
errInvalidMessage = errors.New("invalid message")
protov2MarshalOpts = proto.MarshalOptions{Deterministic: true}
)
// NewInitBuilder creates a new InitBuilder instance.
@ -129,7 +131,7 @@ func (r *ExecuteBuilder) makeResponseEncoder() func(executeResponse any) ([]byte
// we do not check if it is part of an account's valid response message set
// as make handler will never allow for an invalid response to be returned.
return proto.Marshal(anyPB)
return protov2MarshalOpts.Marshal(anyPB)
}
}

View File

@ -18,6 +18,7 @@ require (
github.com/cosmos/cosmos-proto v1.0.0-beta.3
github.com/cosmos/cosmos-sdk v0.51.0
github.com/cosmos/gogoproto v1.4.11
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0
github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.3
github.com/google/gofuzz v1.2.0
@ -60,7 +61,6 @@ require (
github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
github.com/dgraph-io/ristretto v0.1.1 // indirect

View File

@ -10,6 +10,11 @@ import (
"cosmossdk.io/x/tx/signing"
)
var (
_ signing.SignModeHandler = SignModeHandler{}
protov2MarshalOpts = proto.MarshalOptions{Deterministic: true}
)
// SignModeHandler is the SIGN_MODE_DIRECT implementation of signing.SignModeHandler.
type SignModeHandler struct{}
@ -20,12 +25,10 @@ func (h SignModeHandler) Mode() signingv1beta1.SignMode {
// GetSignBytes implements signing.SignModeHandler.GetSignBytes.
func (SignModeHandler) GetSignBytes(_ context.Context, signerData signing.SignerData, txData signing.TxData) ([]byte, error) {
return proto.Marshal(&txv1beta1.SignDoc{
return protov2MarshalOpts.Marshal(&txv1beta1.SignDoc{
BodyBytes: txData.BodyBytes,
AuthInfoBytes: txData.AuthInfoBytes,
ChainId: signerData.ChainID,
AccountNumber: signerData.AccountNumber,
})
}
var _ signing.SignModeHandler = SignModeHandler{}

View File

@ -101,5 +101,7 @@ func (h SignModeHandler) GetSignBytes(
AccountNumber: signerData.AccountNumber,
Sequence: signerData.Sequence,
}
return proto.Marshal(signDocDirectAux)
protov2MarshalOpts := proto.MarshalOptions{Deterministic: true}
return protov2MarshalOpts.Marshal(signDocDirectAux)
}

View File

@ -59,11 +59,13 @@ func MakeHandlerArguments(options HandlerArgumentOptions) (signing.SignerData, s
SignerInfos: signerInfo,
}
bodyBz, err := proto.Marshal(txBody)
protov2MarshalOpts := proto.MarshalOptions{Deterministic: true}
bodyBz, err := protov2MarshalOpts.Marshal(txBody)
if err != nil {
return signing.SignerData{}, signing.TxData{}, err
}
authInfoBz, err := proto.Marshal(authInfo)
authInfoBz, err := protov2MarshalOpts.Marshal(authInfo)
if err != nil {
return signing.SignerData{}, signing.TxData{}, err
}

View File

@ -272,11 +272,12 @@ func (vr txValueRenderer) Parse(ctx context.Context, screens []Screen) (protoref
// Note that we might not always get back the exact bodyBz and authInfoBz
// that was passed into, because protobuf is not deterministic.
// In tests, we don't check bytes equality, but protobuf object equality.
bodyBz, err := proto.Marshal(txBody)
protov2MarshalOpts := proto.MarshalOptions{Deterministic: true}
bodyBz, err := protov2MarshalOpts.Marshal(txBody)
if err != nil {
return nilValue, err
}
authInfoBz, err := proto.Marshal(authInfo)
authInfoBz, err := protov2MarshalOpts.Marshal(authInfo)
if err != nil {
return nilValue, err
}