fix: Remove google.golang.org/protobuf Any prefix (#14119)

* refactor: Remove Any's ypes.googleapis.com prefix

* Add docs

* go mod tidy

* Update
This commit is contained in:
Amaury 2022-12-01 19:09:01 +01:00 committed by GitHub
parent 4cfc79ad4e
commit 0c65734bbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 21 deletions

View File

@ -4,6 +4,7 @@ import (
"fmt"
"strings"
"github.com/cosmos/cosmos-proto/any"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@ -41,7 +42,7 @@ func LoadYAML(bz []byte) depinject.Config {
// WrapAny marshals a proto message into a proto Any instance
func WrapAny(config protoreflect.ProtoMessage) *anypb.Any {
cfg, err := anypb.New(config)
cfg, err := any.New(config)
if err != nil {
panic(err)
}

View File

@ -244,6 +244,34 @@ A real-life example of encoding the pubkey as `Any` inside the Validator struct
https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/staking/types/validator.go#L40-L61
```
#### `Any`'s TypeURL
When packing a protobuf message inside an `Any`, the message's type is uniquely defined by its type URL, which is the message's fully qualified name prefixed by a `/` (slash) character. In some implementations of `Any`, like the gogoproto one, there's generally [a resolvable prefix, e.g. `type.googleapis.com`](https://github.com/gogo/protobuf/blob/b03c65ea87cdc3521ede29f62fe3ce239267c1bc/protobuf/google/protobuf/any.proto#L87-L91). However, in the Cosmos SDK, we made the decision to not include such prefix, to have shorter type URLs. The Cosmos SDK's own `Any` implementation can be found in `github.com/cosmos/cosmos-sdk/codec/types`.
The Cosmos SDK is also switching away from gogoproto to the official `google.golang.org/protobuf` (known as the Protobuf API v2). Its default `Any` implementation also contains the [`type.googleapis.com`](https://github.com/protocolbuffers/protobuf-go/blob/v1.28.1/types/known/anypb/any.pb.go#L266) prefix. To maintain compatibility with the SDK, the following methods from `"google.golang.org/protobuf/types/known/anypb"` should not be used:
- `anypb.New`
- `anypb.MarshalFrom`
- `anypb.Any#MarshalFrom`
Instead, the Cosmos SDK provides helper functions in `"github.com/cosmos/cosmos-proto/any"`, which create an official `anypb.Any` without inserting the prefixes:
- `any.New`
- `any.MarshalFrom`
For example, to pack a `sdk.Msg` called `internalMsg`, use:
```diff
import (
- "google.golang.org/protobuf/types/known/anypb"
+ "github.com/cosmos/cosmos-proto/any"
)
- anyMsg, err := anypb.New(internalMsg.Message().Interface())
+ anyMsg, err := any.New(internalMsg.Message().Interface())
- fmt.Println(anyMsg.TypeURL) // type.googleapis.com/cosmos.bank.v1beta1.MsgSend
+ fmt.Println(anyMsg.TypeURL) // /cosmos.bank.v1beta1.MsgSend
```
## FAQ
### How to create modules using protobuf encoding

View File

@ -10,11 +10,12 @@ import (
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
basev1beta1 "cosmossdk.io/api/cosmos/base/v1beta1"
txv1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1"
"github.com/cosmos/cosmos-proto/any"
"github.com/cosmos/cosmos-sdk/orm/internal/stablejson"
)
func TestStableJSON(t *testing.T) {
msg, err := anypb.New(&bankv1beta1.MsgSend{
msg, err := any.New(&bankv1beta1.MsgSend{
FromAddress: "foo213325",
ToAddress: "foo32t5sdfh",
Amount: []*basev1beta1.Coin{

View File

@ -1,74 +1,74 @@
[
{
"proto": {
"@type": "type.googleapis.com/Foo"
"@type": "/Foo"
},
"screens": [
{"text": "Object: type.googleapis.com/Foo"},
{"text": "Object: /Foo"},
{"text": "Foo object", "indent": 1}
]
},
{
"proto": {
"@type": "type.googleapis.com/Foo",
"@type": "/Foo",
"full_name": "testing"
},
"screens": [
{"text": "Object: type.googleapis.com/Foo"},
{"text": "Object: /Foo"},
{"text": "Foo object", "indent": 1},
{"text": "Full name: testing", "indent": 2}
]
},
{
"proto": {
"@type": "type.googleapis.com/google.protobuf.Timestamp",
"@type": "/google.protobuf.Timestamp",
"value": "2006-01-02T15:04:05Z"
},
"screens": [
{"text": "Object: type.googleapis.com/google.protobuf.Timestamp"},
{"text": "Object: /google.protobuf.Timestamp"},
{"text": "2006-01-02T15:04:05Z", "indent": 1}
]
},
{
"proto": {
"@type": "type.googleapis.com/google.protobuf.Any",
"@type": "/google.protobuf.Any",
"value": {
"@type": "type.googleapis.com/Foo"
"@type": "/Foo"
}
},
"screens": [
{"text": "Object: type.googleapis.com/google.protobuf.Any"},
{"text": "Object: type.googleapis.com/Foo", "indent": 1},
{"text": "Object: /google.protobuf.Any"},
{"text": "Object: /Foo", "indent": 1},
{"text": "Foo object", "indent": 2}
]
},
{
"proto": {
"@type": "type.googleapis.com/google.protobuf.Any",
"@type": "/google.protobuf.Any",
"value": {
"@type": "type.googleapis.com/Foo",
"@type": "/Foo",
"full_name": "testing"
}
},
"screens": [
{"text": "Object: type.googleapis.com/google.protobuf.Any"},
{"text": "Object: type.googleapis.com/Foo", "indent": 1},
{"text": "Object: /google.protobuf.Any"},
{"text": "Object: /Foo", "indent": 1},
{"text": "Foo object", "indent": 2},
{"text": "Full name: testing", "indent": 3}
]
},
{
"proto": {
"@type": "type.googleapis.com/A",
"@type": "/A",
"ANY": {
"@type": "type.googleapis.com/Foo",
"@type": "/Foo",
"full_name": "testing"
}
},
"screens": [
{"text": "Object: type.googleapis.com/A"},
{"text": "Object: /A"},
{"text": "A object", "indent": 1},
{"text": "ANY: Object: type.googleapis.com/Foo", "indent": 2},
{"text": "ANY: Object: /Foo", "indent": 2},
{"text": "Foo object", "indent": 3},
{"text": "Full name: testing", "indent": 4}
]

View File

@ -5,6 +5,7 @@ import (
"fmt"
"strings"
"github.com/cosmos/cosmos-proto/any"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/types/known/anypb"
@ -93,7 +94,7 @@ func (ar anyValueRenderer) Parse(ctx context.Context, screens []Screen) (protore
return nilValue, err
}
anyMsg, err := anypb.New(internalMsg.Message().Interface())
anyMsg, err := any.New(internalMsg.Message().Interface())
if err != nil {
return nilValue, err
}