Add ADR 031 BaseApp and codec infrastructure (#7519)

* Refactor RegisterQueryServices -> RegisterServices

* Cleaner proto files

* Fix tests

* Add MsgServer

* Fix lint

* Remove MsgServer from configurator for now

* Remove useless file

* Fix build

* typo

* Add router

* Fix test

* WIP

* Add router

* Remove test helper

* Add beginning of test

* Move test to simapp?

* ServiceMsg implement sdk.Msg

* Add handler by MsgServiceRouter

* Correct signature

* Add full test

* use TxEncoder

* Update baseapp/msg_service_router.go

Co-authored-by: Aaron Craelius <aaron@regen.network>

* Push changes

* WIP on ServiceMsg unpacking

* Make TestMsgService test pass

* Fix tests

* Tidying up

* Tidying up

* Tidying up

* Add JSON test

* Add comments

* Tidying

* Lint

* Register MsgRequest interface

* Rename

* Fix tests

* RegisterCustomTypeURL

* Add changelog entries

* Put in features

* Update baseapp/msg_service_router.go

Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>

* Update baseapp/msg_service_router.go

Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>

* Update baseapp/msg_service_router.go

Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>

* Update baseapp/msg_service_router.go

Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>

* Update baseapp/msg_service_router.go

Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>

* Update baseapp/msg_service_router.go

Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>

* Update baseapp/msg_service_router.go

Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>

* Address review comments

* Address nit

* Fix lint

* Update codec/types/interface_registry.go

Co-authored-by: Marie Gauthier <marie.gauthier63@gmail.com>

* godoc

Co-authored-by: Aaron Craelius <aaronc@users.noreply.github.com>
Co-authored-by: Aaron Craelius <aaron@regen.network>
Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>
Co-authored-by: Marie Gauthier <marie.gauthier63@gmail.com>
This commit is contained in:
Amaury Martiny
2020-10-15 13:07:59 +00:00
committed by GitHub
co-authored by Aaron Craelius Aleksandr Bezobchuk Marie Gauthier Aaron Craelius
parent e6e4a94071
commit 55242a659c
49 changed files with 5274 additions and 3850 deletions
+2 -2
View File
@@ -56,7 +56,7 @@ func benchmarkRejectUnknownFields(b *testing.B, parallel bool) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
n1A := new(testdata.Nested1A)
if err := unknownproto.RejectUnknownFieldsStrict(n1BBlob, n1A); err == nil {
if err := unknownproto.RejectUnknownFieldsStrict(n1BBlob, n1A, unknownproto.DefaultAnyResolver{}); err == nil {
b.Fatal("expected an error")
}
b.SetBytes(int64(len(n1BBlob)))
@@ -68,7 +68,7 @@ func benchmarkRejectUnknownFields(b *testing.B, parallel bool) {
for pb.Next() {
// To simulate the conditions of multiple transactions being processed in parallel.
n1A := new(testdata.Nested1A)
if err := unknownproto.RejectUnknownFieldsStrict(n1BBlob, n1A); err == nil {
if err := unknownproto.RejectUnknownFieldsStrict(n1BBlob, n1A, unknownproto.DefaultAnyResolver{}); err == nil {
b.Fatal("expected an error")
}
mu.Lock()
+41 -10
View File
@@ -7,8 +7,10 @@ import (
"fmt"
"io/ioutil"
"reflect"
"strings"
"sync"
"github.com/gogo/protobuf/jsonpb"
"github.com/gogo/protobuf/proto"
"github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"google.golang.org/protobuf/encoding/protowire"
@@ -24,8 +26,9 @@ type descriptorIface interface {
// RejectUnknownFieldsStrict rejects any bytes bz with an error that has unknown fields for the provided proto.Message type.
// This function traverses inside of messages nested via google.protobuf.Any. It does not do any deserialization of the proto.Message.
func RejectUnknownFieldsStrict(bz []byte, msg proto.Message) error {
_, err := RejectUnknownFields(bz, msg, false)
// An AnyResolver must be provided for traversing inside google.protobuf.Any's.
func RejectUnknownFieldsStrict(bz []byte, msg proto.Message, resolver jsonpb.AnyResolver) error {
_, err := RejectUnknownFields(bz, msg, false, resolver)
return err
}
@@ -34,7 +37,8 @@ func RejectUnknownFieldsStrict(bz []byte, msg proto.Message) error {
// hasUnknownNonCriticals will be set to true if non-critical fields were encountered during traversal. This flag can be
// used to treat a message with non-critical field different in different security contexts (such as transaction signing).
// This function traverses inside of messages nested via google.protobuf.Any. It does not do any deserialization of the proto.Message.
func RejectUnknownFields(bz []byte, msg proto.Message, allowUnknownNonCriticals bool) (hasUnknownNonCriticals bool, err error) {
// An AnyResolver must be provided for traversing inside google.protobuf.Any's.
func RejectUnknownFields(bz []byte, msg proto.Message, allowUnknownNonCriticals bool, resolver jsonpb.AnyResolver) (hasUnknownNonCriticals bool, err error) {
if len(bz) == 0 {
return hasUnknownNonCriticals, nil
}
@@ -115,9 +119,12 @@ func RejectUnknownFields(bz []byte, msg proto.Message, allowUnknownNonCriticals
_, o := protowire.ConsumeVarint(fieldBytes)
fieldBytes = fieldBytes[o:]
var msg proto.Message
var err error
if protoMessageName == ".google.protobuf.Any" {
// Firstly typecheck types.Any to ensure nothing snuck in.
hasUnknownNonCriticalsChild, err := RejectUnknownFields(fieldBytes, (*types.Any)(nil), allowUnknownNonCriticals)
hasUnknownNonCriticalsChild, err := RejectUnknownFields(fieldBytes, (*types.Any)(nil), allowUnknownNonCriticals, resolver)
hasUnknownNonCriticals = hasUnknownNonCriticals || hasUnknownNonCriticalsChild
if err != nil {
return hasUnknownNonCriticals, err
@@ -129,14 +136,18 @@ func RejectUnknownFields(bz []byte, msg proto.Message, allowUnknownNonCriticals
}
protoMessageName = any.TypeUrl
fieldBytes = any.Value
msg, err = resolver.Resolve(protoMessageName)
if err != nil {
return hasUnknownNonCriticals, err
}
} else {
msg, err = protoMessageForTypeName(protoMessageName[1:])
if err != nil {
return hasUnknownNonCriticals, err
}
}
msg, err := protoMessageForTypeName(protoMessageName[1:])
if err != nil {
return hasUnknownNonCriticals, err
}
hasUnknownNonCriticalsChild, err := RejectUnknownFields(fieldBytes, msg, allowUnknownNonCriticals)
hasUnknownNonCriticalsChild, err := RejectUnknownFields(fieldBytes, msg, allowUnknownNonCriticals, resolver)
hasUnknownNonCriticals = hasUnknownNonCriticals || hasUnknownNonCriticalsChild
if err != nil {
return hasUnknownNonCriticals, err
@@ -401,3 +412,23 @@ func getDescriptorInfo(desc descriptorIface, msg proto.Message) (map[int32]*desc
return tagNumToTypeIndex, md, nil
}
// DefaultAnyResolver is a default implementation of AnyResolver which uses
// the default encoding of type URLs as specified by the protobuf specification.
type DefaultAnyResolver struct{}
var _ jsonpb.AnyResolver = DefaultAnyResolver{}
// Resolve is the AnyResolver.Resolve method.
func (d DefaultAnyResolver) Resolve(typeURL string) (proto.Message, error) {
// Only the part of typeURL after the last slash is relevant.
mname := typeURL
if slash := strings.LastIndex(mname, "/"); slash >= 0 {
mname = mname[slash+1:]
}
mt := proto.MessageType(mname)
if mt == nil {
return nil, fmt.Errorf("unknown message type %q", mname)
}
return reflect.New(mt.Elem()).Interface().(proto.Message), nil
}
+5 -5
View File
@@ -230,7 +230,7 @@ func TestRejectUnknownFieldsRepeated(t *testing.T) {
if err != nil {
t.Fatal(err)
}
hasUnknownNonCriticals, gotErr := RejectUnknownFields(protoBlob, tt.recv, tt.allowUnknownNonCriticals)
hasUnknownNonCriticals, gotErr := RejectUnknownFields(protoBlob, tt.recv, tt.allowUnknownNonCriticals, DefaultAnyResolver{})
require.Equal(t, tt.wantErr, gotErr)
require.Equal(t, tt.hasUnknownNonCriticals, hasUnknownNonCriticals)
})
@@ -289,7 +289,7 @@ func TestRejectUnknownFields_allowUnknownNonCriticals(t *testing.T) {
}
c1 := new(testdata.Customer1)
_, gotErr := RejectUnknownFields(blob, c1, tt.allowUnknownNonCriticals)
_, gotErr := RejectUnknownFields(blob, c1, tt.allowUnknownNonCriticals, DefaultAnyResolver{})
if !reflect.DeepEqual(gotErr, tt.wantErr) {
t.Fatalf("Error mismatch\nGot:\n%s\n\nWant:\n%s", gotErr, tt.wantErr)
}
@@ -490,7 +490,7 @@ func TestRejectUnknownFieldsNested(t *testing.T) {
if err != nil {
t.Fatal(err)
}
gotErr := RejectUnknownFieldsStrict(protoBlob, tt.recv)
gotErr := RejectUnknownFieldsStrict(protoBlob, tt.recv, DefaultAnyResolver{})
if !reflect.DeepEqual(gotErr, tt.wantErr) {
t.Fatalf("Error mismatch\nGot:\n%s\n\nWant:\n%s", gotErr, tt.wantErr)
}
@@ -643,7 +643,7 @@ func TestRejectUnknownFieldsFlat(t *testing.T) {
}
c1 := new(testdata.Customer1)
gotErr := RejectUnknownFieldsStrict(blob, c1)
gotErr := RejectUnknownFieldsStrict(blob, c1, DefaultAnyResolver{})
if !reflect.DeepEqual(gotErr, tt.wantErr) {
t.Fatalf("Error mismatch\nGot:\n%s\n\nWant:\n%s", gotErr, tt.wantErr)
}
@@ -660,7 +660,7 @@ func TestPackedEncoding(t *testing.T) {
require.NoError(t, err)
unmarshalled := &testdata.TestRepeatedUints{}
_, err = RejectUnknownFields(marshalled, unmarshalled, false)
_, err = RejectUnknownFields(marshalled, unmarshalled, false, DefaultAnyResolver{})
require.NoError(t, err)
}