feat(codec): add collections value codec for protov2 APIs. (#17042)
Co-authored-by: unknown unknown <unknown@unknown>
This commit is contained in:
parent
c23505b037
commit
3d15233578
@ -43,6 +43,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
* (baseapp) [#16898](https://github.com/cosmos/cosmos-sdk/pull/16898) Add `preFinalizeBlockHook` to allow vote extensions persistence.
|
||||
* (cli) [#16887](https://github.com/cosmos/cosmos-sdk/pull/16887) Add two new CLI commands: `tx simulate` for simulating a transaction; `query block-results` for querying CometBFT RPC for block results.
|
||||
* (x/gov) [#16976](https://github.com/cosmos/cosmos-sdk/pull/16976) Add `failed_reason` field to `Proposal` under `x/gov` to indicate the reason for a failed proposal. Referenced from [#238](https://github.com/bnb-chain/greenfield-cosmos-sdk/pull/238) under `bnb-chain/greenfield-cosmos-sdk`.
|
||||
* (codec) [#17042](https://github.com/cosmos/cosmos-sdk/pull/17042) Add `CollValueV2` which supports encoding of protov2 messages in collections.
|
||||
|
||||
### Improvements
|
||||
|
||||
|
||||
@ -6,6 +6,8 @@ import (
|
||||
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
gogotypes "github.com/cosmos/gogoproto/types"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
protov2 "google.golang.org/protobuf/proto"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
collcodec "cosmossdk.io/collections/codec"
|
||||
@ -51,10 +53,13 @@ type protoMessage[T any] interface {
|
||||
|
||||
// CollValue inits a collections.ValueCodec for a generic gogo protobuf message.
|
||||
func CollValue[T any, PT protoMessage[T]](cdc BinaryCodec) collcodec.ValueCodec[T] {
|
||||
return &collValue[T, PT]{cdc.(Codec)}
|
||||
return &collValue[T, PT]{cdc.(Codec), proto.MessageName(PT(new(T)))}
|
||||
}
|
||||
|
||||
type collValue[T any, PT protoMessage[T]] struct{ cdc Codec }
|
||||
type collValue[T any, PT protoMessage[T]] struct {
|
||||
cdc Codec
|
||||
messageName string
|
||||
}
|
||||
|
||||
func (c collValue[T, PT]) Encode(value T) ([]byte, error) {
|
||||
return c.cdc.Marshal(PT(&value))
|
||||
@ -79,7 +84,51 @@ func (c collValue[T, PT]) Stringify(value T) string {
|
||||
}
|
||||
|
||||
func (c collValue[T, PT]) ValueType() string {
|
||||
return "gogoproto/" + proto.MessageName(PT(new(T)))
|
||||
return "github.com/cosmos/gogoproto/" + c.messageName
|
||||
}
|
||||
|
||||
type protoMessageV2[T any] interface {
|
||||
*T
|
||||
protov2.Message
|
||||
}
|
||||
|
||||
// CollValueV2 is used for protobuf values of the newest google.golang.org/protobuf API.
|
||||
func CollValueV2[T any, PT protoMessageV2[T]]() collcodec.ValueCodec[PT] {
|
||||
return &collValue2[T, PT]{
|
||||
messageName: string(PT(new(T)).ProtoReflect().Descriptor().FullName()),
|
||||
}
|
||||
}
|
||||
|
||||
type collValue2[T any, PT protoMessageV2[T]] struct {
|
||||
messageName string
|
||||
}
|
||||
|
||||
func (c collValue2[T, PT]) Encode(value PT) ([]byte, error) {
|
||||
return protov2.Marshal(value)
|
||||
}
|
||||
|
||||
func (c collValue2[T, PT]) Decode(b []byte) (PT, error) {
|
||||
var value T
|
||||
err := protov2.Unmarshal(b, PT(&value))
|
||||
return &value, err
|
||||
}
|
||||
|
||||
func (c collValue2[T, PT]) EncodeJSON(value PT) ([]byte, error) {
|
||||
return protojson.Marshal(value)
|
||||
}
|
||||
|
||||
func (c collValue2[T, PT]) DecodeJSON(b []byte) (PT, error) {
|
||||
var value T
|
||||
err := protojson.Unmarshal(b, PT(&value))
|
||||
return &value, err
|
||||
}
|
||||
|
||||
func (c collValue2[T, PT]) Stringify(value PT) string {
|
||||
return fmt.Sprintf("%v", value)
|
||||
}
|
||||
|
||||
func (c collValue2[T, PT]) ValueType() string {
|
||||
return "google.golang.org/protobuf/" + c.messageName
|
||||
}
|
||||
|
||||
// CollInterfaceValue instantiates a new collections.ValueCodec for a generic
|
||||
|
||||
@ -4,7 +4,10 @@ import (
|
||||
"testing"
|
||||
|
||||
gogotypes "github.com/cosmos/gogoproto/types"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/testing/protocmp"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
|
||||
"cosmossdk.io/collections/colltest"
|
||||
|
||||
@ -21,6 +24,28 @@ func TestCollectionsCorrectness(t *testing.T) {
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("CollValueV2", func(t *testing.T) {
|
||||
// NOTE: we cannot use colltest.TestValueCodec because protov2 has different
|
||||
// compare semantics than protov1. We need to use protocmp.Transform() alongside
|
||||
// cmp to ensure equality.
|
||||
encoder := codec.CollValueV2[wrapperspb.UInt64Value]()
|
||||
value := &wrapperspb.UInt64Value{Value: 500}
|
||||
encodedValue, err := encoder.Encode(value)
|
||||
require.NoError(t, err)
|
||||
decodedValue, err := encoder.Decode(encodedValue)
|
||||
require.NoError(t, err)
|
||||
require.True(t, cmp.Equal(value, decodedValue, protocmp.Transform()), "encoding and decoding produces different values")
|
||||
|
||||
encodedJSONValue, err := encoder.EncodeJSON(value)
|
||||
require.NoError(t, err)
|
||||
decodedJSONValue, err := encoder.DecodeJSON(encodedJSONValue)
|
||||
require.NoError(t, err)
|
||||
require.True(t, cmp.Equal(value, decodedJSONValue, protocmp.Transform()), "encoding and decoding produces different values")
|
||||
require.NotEmpty(t, encoder.ValueType())
|
||||
|
||||
_ = encoder.Stringify(value)
|
||||
})
|
||||
|
||||
t.Run("BoolValue", func(t *testing.T) {
|
||||
colltest.TestValueCodec(t, codec.BoolValue, true)
|
||||
colltest.TestValueCodec(t, codec.BoolValue, false)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user