cosmos-sdk/codec/proto_codec.go
Robert Zaremba 7568b6680a
Remove bech32 PubKey support (#7477)
* Move PubKey bech32 to legacy package and migrate the usage where possible

* update /server

* wip

* move proto json encoding helper functions to internal

* update internal/marshal

* wip

* update sections which needs legacybech32

* update validators output

* fix conflicts

* slashing update

* add more tests and helper function for ANY JSON serialization

* update slashing

* Update function documentation

* Rename code any-marshal helper functions

* Update pubkey unpacking test

* Update test comments

* solve TestDecodeStore

* solve legacytx issues

* all code compiles

* keyring tests

* keyring cleanup

* remove AssertMsg

* fix some tests

* fix add_ledger_test.go

* update cli tests

* debug cli test

* rename clashed bech32 names

* linter fixes

* update tmservice tests

* linter: update legacy deprecated checks

* fix names

* linting

* legacybech32 pubkey type rename

* fix staking client

* fix test compilation

* fix TestGetCmdQuerySigningInfo

* rename NewIfcJSONAnyMarshaler

* keyring: remove duplicated information from multinfo structure

* todo cleanups

* Update Changelog

* remove some legacybech32 from tests

* remove todos

* remove printlnJSON from /server CLI and amino encoding

* remove protocdc.MarshalJSON

* client/show remove duplicated function

* remove protocdc package

* comment update

* remove legacybech32.MustMarshalPubKey from a test

* add todo

* fix TestPublicKeyUnsafe test

* review update

* fix bech32 UnmarshalPubKey

* Use codec.MarshalIfcJSON

* fix linter issues

* merging conflict: fix codec.Unmarshal calls

* cleanups

* Update CHANGELOG.md

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

* Reword changelog updates

* use pubkey.String for comparison in Test_runAddCmdLedgerWithCustomCoinType

* Update GetCmdQuerySigningInfo example

* cli: update keys add docs

* Add errors AsOf and errors.ErrIO type

* restore multisigPubKeyInfo structure bring it back to multiInfo struct

* Update codec/proto_codec.go

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

* Update crypto/keys/ed25519/ed25519_test.go

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

* Update codec/proto_codec.go

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

* move pubkey any marshaling tests

* Apply suggestions from code review

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

* review updates

* adding missing return

* errors: use IsOf instead of AsOf

* keyring: add a correct check for key not found in keyring.Get

* add checkKeyNotFound

* fix linter issues

* fix: keyring key not found check

* fix keyring tests

* fix linting issues

* cli tests

* fix: 'simd keys show <key> -p'

* fix: TestVerifyMultisignature

* rename keyring Bech32... functions to Mk...

* fix RunAddCmd

* Update pubkey display

* wip

* add more tests

* udate keyring output tests

* remove todo from ledger tests

* rename MkKeyOutput

* Changelog update

* solve liner issues

* add link to github issue

Co-authored-by: Aaron Craelius <aaron@regen.network>
Co-authored-by: Marie Gauthier <marie.gauthier63@gmail.com>
2021-03-25 14:53:22 +00:00

259 lines
8.5 KiB
Go

package codec
import (
"encoding/binary"
"errors"
"fmt"
"strings"
"github.com/gogo/protobuf/jsonpb"
"github.com/gogo/protobuf/proto"
"github.com/cosmos/cosmos-sdk/codec/types"
)
// ProtoCodecMarshaler defines an interface for codecs that utilize Protobuf for both
// binary and JSON encoding.
type ProtoCodecMarshaler interface {
Marshaler
InterfaceRegistry() types.InterfaceRegistry
}
// ProtoCodec defines a codec that utilizes Protobuf for both binary and JSON
// encoding.
type ProtoCodec struct {
interfaceRegistry types.InterfaceRegistry
}
var _ Marshaler = &ProtoCodec{}
var _ ProtoCodecMarshaler = &ProtoCodec{}
// NewProtoCodec returns a reference to a new ProtoCodec
func NewProtoCodec(interfaceRegistry types.InterfaceRegistry) *ProtoCodec {
return &ProtoCodec{interfaceRegistry: interfaceRegistry}
}
// MarshalBinaryBare implements BinaryMarshaler.MarshalBinaryBare method.
// NOTE: this function must be used with a concrete type which
// implements proto.Message. For interface please use the codec.MarshalInterface
func (pc *ProtoCodec) MarshalBinaryBare(o ProtoMarshaler) ([]byte, error) {
return o.Marshal()
}
// MustMarshalBinaryBare implements BinaryMarshaler.MustMarshalBinaryBare method.
// NOTE: this function must be used with a concrete type which
// implements proto.Message. For interface please use the codec.MarshalInterface
func (pc *ProtoCodec) MustMarshalBinaryBare(o ProtoMarshaler) []byte {
bz, err := pc.MarshalBinaryBare(o)
if err != nil {
panic(err)
}
return bz
}
// MarshalBinaryLengthPrefixed implements BinaryMarshaler.MarshalBinaryLengthPrefixed method.
func (pc *ProtoCodec) MarshalBinaryLengthPrefixed(o ProtoMarshaler) ([]byte, error) {
bz, err := pc.MarshalBinaryBare(o)
if err != nil {
return nil, err
}
var sizeBuf [binary.MaxVarintLen64]byte
n := binary.PutUvarint(sizeBuf[:], uint64(o.Size()))
return append(sizeBuf[:n], bz...), nil
}
// MustMarshalBinaryLengthPrefixed implements BinaryMarshaler.MustMarshalBinaryLengthPrefixed method.
func (pc *ProtoCodec) MustMarshalBinaryLengthPrefixed(o ProtoMarshaler) []byte {
bz, err := pc.MarshalBinaryLengthPrefixed(o)
if err != nil {
panic(err)
}
return bz
}
// UnmarshalBinaryBare implements BinaryMarshaler.UnmarshalBinaryBare method.
// NOTE: this function must be used with a concrete type which
// implements proto.Message. For interface please use the codec.UnmarshalInterface
func (pc *ProtoCodec) UnmarshalBinaryBare(bz []byte, ptr ProtoMarshaler) error {
err := ptr.Unmarshal(bz)
if err != nil {
return err
}
err = types.UnpackInterfaces(ptr, pc.interfaceRegistry)
if err != nil {
return err
}
return nil
}
// MustUnmarshalBinaryBare implements BinaryMarshaler.MustUnmarshalBinaryBare method.
// NOTE: this function must be used with a concrete type which
// implements proto.Message. For interface please use the codec.UnmarshalInterface
func (pc *ProtoCodec) MustUnmarshalBinaryBare(bz []byte, ptr ProtoMarshaler) {
if err := pc.UnmarshalBinaryBare(bz, ptr); err != nil {
panic(err)
}
}
// UnmarshalBinaryLengthPrefixed implements BinaryMarshaler.UnmarshalBinaryLengthPrefixed method.
func (pc *ProtoCodec) UnmarshalBinaryLengthPrefixed(bz []byte, ptr ProtoMarshaler) error {
size, n := binary.Uvarint(bz)
if n < 0 {
return fmt.Errorf("invalid number of bytes read from length-prefixed encoding: %d", n)
}
if size > uint64(len(bz)-n) {
return fmt.Errorf("not enough bytes to read; want: %v, got: %v", size, len(bz)-n)
} else if size < uint64(len(bz)-n) {
return fmt.Errorf("too many bytes to read; want: %v, got: %v", size, len(bz)-n)
}
bz = bz[n:]
return pc.UnmarshalBinaryBare(bz, ptr)
}
// MustUnmarshalBinaryLengthPrefixed implements BinaryMarshaler.MustUnmarshalBinaryLengthPrefixed method.
func (pc *ProtoCodec) MustUnmarshalBinaryLengthPrefixed(bz []byte, ptr ProtoMarshaler) {
if err := pc.UnmarshalBinaryLengthPrefixed(bz, ptr); err != nil {
panic(err)
}
}
// MarshalJSON implements JSONMarshaler.MarshalJSON method,
// it marshals to JSON using proto codec.
// NOTE: this function must be used with a concrete type which
// implements proto.Message. For interface please use the codec.MarshalInterfaceJSON
func (pc *ProtoCodec) MarshalJSON(o proto.Message) ([]byte, error) {
m, ok := o.(ProtoMarshaler)
if !ok {
return nil, fmt.Errorf("cannot protobuf JSON encode unsupported type: %T", o)
}
return ProtoMarshalJSON(m, pc.interfaceRegistry)
}
// MustMarshalJSON implements JSONMarshaler.MustMarshalJSON method,
// it executes MarshalJSON except it panics upon failure.
// NOTE: this function must be used with a concrete type which
// implements proto.Message. For interface please use the codec.MarshalInterfaceJSON
func (pc *ProtoCodec) MustMarshalJSON(o proto.Message) []byte {
bz, err := pc.MarshalJSON(o)
if err != nil {
panic(err)
}
return bz
}
// UnmarshalJSON implements JSONMarshaler.UnmarshalJSON method,
// it unmarshals from JSON using proto codec.
// NOTE: this function must be used with a concrete type which
// implements proto.Message. For interface please use the codec.UnmarshalInterfaceJSON
func (pc *ProtoCodec) UnmarshalJSON(bz []byte, ptr proto.Message) error {
m, ok := ptr.(ProtoMarshaler)
if !ok {
return fmt.Errorf("cannot protobuf JSON decode unsupported type: %T", ptr)
}
unmarshaler := jsonpb.Unmarshaler{AnyResolver: pc.interfaceRegistry}
err := unmarshaler.Unmarshal(strings.NewReader(string(bz)), m)
if err != nil {
return err
}
return types.UnpackInterfaces(ptr, pc.interfaceRegistry)
}
// MustUnmarshalJSON implements JSONMarshaler.MustUnmarshalJSON method,
// it executes UnmarshalJSON except it panics upon failure.
// NOTE: this function must be used with a concrete type which
// implements proto.Message. For interface please use the codec.UnmarshalInterfaceJSON
func (pc *ProtoCodec) MustUnmarshalJSON(bz []byte, ptr proto.Message) {
if err := pc.UnmarshalJSON(bz, ptr); err != nil {
panic(err)
}
}
// MarshalInterface is a convenience function for proto marshalling interfaces. It packs
// the provided value, which must be an interface, in an Any and then marshals it to bytes.
// NOTE: to marshal a concrete type, you should use MarshalBinaryBare instead
func (pc *ProtoCodec) MarshalInterface(i proto.Message) ([]byte, error) {
if err := assertNotNil(i); err != nil {
return nil, err
}
any, err := types.NewAnyWithValue(i)
if err != nil {
return nil, err
}
return pc.MarshalBinaryBare(any)
}
// UnmarshalInterface is a convenience function for proto unmarshaling interfaces. It
// unmarshals an Any from bz bytes and then unpacks it to the `ptr`, which must
// be a pointer to a non empty interface with registered implementations.
// NOTE: to unmarshal a concrete type, you should use UnmarshalBinaryBare instead
//
// Example:
// var x MyInterface
// err := cdc.UnmarshalInterface(bz, &x)
func (pc *ProtoCodec) UnmarshalInterface(bz []byte, ptr interface{}) error {
any := &types.Any{}
err := pc.UnmarshalBinaryBare(bz, any)
if err != nil {
return err
}
return pc.UnpackAny(any, ptr)
}
// MarshalInterfaceJSON is a convenience function for proto marshalling interfaces. It
// packs the provided value in an Any and then marshals it to bytes.
// NOTE: to marshal a concrete type, you should use MarshalJSON instead
func (pc *ProtoCodec) MarshalInterfaceJSON(x proto.Message) ([]byte, error) {
any, err := types.NewAnyWithValue(x)
if err != nil {
return nil, err
}
return pc.MarshalJSON(any)
}
// UnmarshalInterfaceJSON is a convenience function for proto unmarshaling interfaces.
// It unmarshals an Any from bz bytes and then unpacks it to the `iface`, which must
// be a pointer to a non empty interface, implementing proto.Message with registered implementations.
// NOTE: to unmarshal a concrete type, you should use UnmarshalJSON instead
//
// Example:
// var x MyInterface // must implement proto.Message
// err := cdc.UnmarshalInterfaceJSON(&x, bz)
func (pc *ProtoCodec) UnmarshalInterfaceJSON(bz []byte, iface interface{}) error {
any := &types.Any{}
err := pc.UnmarshalJSON(bz, any)
if err != nil {
return err
}
return pc.UnpackAny(any, iface)
}
// UnpackAny implements AnyUnpacker.UnpackAny method,
// it unpacks the value in any to the interface pointer passed in as
// iface.
func (pc *ProtoCodec) UnpackAny(any *types.Any, iface interface{}) error {
return pc.interfaceRegistry.UnpackAny(any, iface)
}
// InterfaceRegistry returns InterfaceRegistry
func (pc *ProtoCodec) InterfaceRegistry() types.InterfaceRegistry {
return pc.interfaceRegistry
}
func assertNotNil(i interface{}) error {
if i == nil {
return errors.New("can't marshal <nil> value")
}
return nil
}