/
fix_registration.go
143 lines (128 loc) · 3.62 KB
/
fix_registration.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package gogoreflection
import (
"bytes"
"compress/gzip"
"fmt"
"reflect"
_ "github.com/gogo/protobuf/gogoproto" // required so it does register the gogoproto file descriptor
gogoproto "github.com/gogo/protobuf/proto"
// nolint: staticcheck
"github.com/golang/protobuf/proto"
dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
_ "github.com/regen-network/cosmos-proto" // look above
)
var importsToFix = map[string]string{
"gogo.proto": "gogoproto/gogo.proto",
"cosmos.proto": "cosmos_proto/cosmos.proto",
}
// fixRegistration is required because certain files register themselves in a way
// but are imported by other files in a different way.
// NOTE(fdymylja): This fix should not be needed and should be addressed in some CI.
// Currently every cosmos-sdk proto file is importing gogo.proto as gogoproto/gogo.proto,
// but gogo.proto registers itself as gogo.proto, same goes for cosmos.proto.
func fixRegistration(registeredAs, importedAs string) error {
raw := gogoproto.FileDescriptor(registeredAs)
if len(raw) == 0 {
return fmt.Errorf("file descriptor not found for %s", registeredAs)
}
fd, err := decodeFileDesc(raw)
if err != nil {
return err
}
// fix name
*fd.Name = importedAs
fixedRaw, err := compress(fd)
if err != nil {
return fmt.Errorf("unable to compress: %w", err)
}
gogoproto.RegisterFile(importedAs, fixedRaw)
return nil
}
func init() {
// we need to fix the gogoproto filedesc to match the import path
// in theory this shouldn't be required, generally speaking
// proto files should be imported as their registration path
for registeredAs, importedAs := range importsToFix {
err := fixRegistration(registeredAs, importedAs)
if err != nil {
panic(err)
}
}
}
// compress compresses the given file descriptor
// nolint: interfacer
func compress(fd *dpb.FileDescriptorProto) ([]byte, error) {
fdBytes, err := proto.Marshal(fd)
if err != nil {
return nil, err
}
buf := new(bytes.Buffer)
cw := gzip.NewWriter(buf)
_, err = cw.Write(fdBytes)
if err != nil {
return nil, err
}
err = cw.Close()
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func getFileDescriptor(filePath string) []byte {
// since we got well known descriptors which are not registered into gogoproto registry
// but are instead registered into the proto one, we need to check both
fd := gogoproto.FileDescriptor(filePath)
if len(fd) != 0 {
return fd
}
// nolint: staticcheck
return proto.FileDescriptor(filePath)
}
func getMessageType(name string) reflect.Type {
typ := gogoproto.MessageType(name)
if typ != nil {
return typ
}
// nolint: staticcheck
return proto.MessageType(name)
}
func getExtension(extID int32, m proto.Message) *gogoproto.ExtensionDesc {
// check first in gogoproto registry
for id, desc := range gogoproto.RegisteredExtensions(m) {
if id == extID {
return desc
}
}
// check into proto registry
// nolint: staticcheck
for id, desc := range proto.RegisteredExtensions(m) {
if id == extID {
return &gogoproto.ExtensionDesc{
ExtendedType: desc.ExtendedType,
ExtensionType: desc.ExtensionType,
Field: desc.Field,
Name: desc.Name,
Tag: desc.Tag,
Filename: desc.Filename,
}
}
}
return nil
}
func getExtensionsNumbers(m proto.Message) []int32 {
gogoProtoExts := gogoproto.RegisteredExtensions(m)
out := make([]int32, 0, len(gogoProtoExts))
for id := range gogoProtoExts {
out = append(out, id)
}
if len(out) != 0 {
return out
}
// nolint: staticcheck
protoExts := proto.RegisteredExtensions(m)
out = make([]int32, 0, len(protoExts))
for id := range protoExts {
out = append(out, id)
}
return out
}