rpc: simplify the encoding of interface-typed arguments in JSON (#7600)

Add package jsontypes that implements a subset of the custom libs/json 
package. Specifically it handles encoding and decoding of interface types
wrapped in "tagged" JSON objects. It omits the deep reflection on arbitrary
types, preserving only the handling of type tags wrapper encoding.

- Register interface types (Evidence, PubKey, PrivKey) for tagged encoding.
- Update the existing implementations to satisfy the type.
- Register those types with the jsontypes registry.
- Add string tags to 64-bit integer fields where needed.
- Add marshalers to structs that export interface-typed fields.
This commit is contained in:
M. J. Fromberger
2022-01-14 18:14:09 -08:00
committed by GitHub
parent 7ed57ef5f9
commit dbe2146d0a
19 changed files with 349 additions and 24 deletions

View File

@@ -2,6 +2,7 @@ package crypto
import (
"github.com/tendermint/tendermint/crypto/tmhash"
"github.com/tendermint/tendermint/internal/jsontypes"
"github.com/tendermint/tendermint/libs/bytes"
)
@@ -25,6 +26,9 @@ type PubKey interface {
VerifySignature(msg []byte, sig []byte) bool
Equals(PubKey) bool
Type() string
// Implementations must support tagged encoding in JSON.
jsontypes.Tagged
}
type PrivKey interface {
@@ -33,6 +37,9 @@ type PrivKey interface {
PubKey() PubKey
Equals(PrivKey) bool
Type() string
// Implementations must support tagged encoding in JSON.
jsontypes.Tagged
}
type Symmetric interface {

View File

@@ -12,6 +12,7 @@ import (
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/tmhash"
"github.com/tendermint/tendermint/internal/jsontypes"
tmjson "github.com/tendermint/tendermint/libs/json"
)
@@ -58,11 +59,17 @@ const (
func init() {
tmjson.RegisterType(PubKey{}, PubKeyName)
tmjson.RegisterType(PrivKey{}, PrivKeyName)
jsontypes.MustRegister(PubKey{})
jsontypes.MustRegister(PrivKey{})
}
// PrivKey implements crypto.PrivKey.
type PrivKey []byte
// TypeTag satisfies the jsontypes.Tagged interface.
func (PrivKey) TypeTag() string { return PrivKeyName }
// Bytes returns the privkey byte format.
func (privKey PrivKey) Bytes() []byte {
return []byte(privKey)
@@ -151,6 +158,9 @@ var _ crypto.PubKey = PubKey{}
// PubKeyEd25519 implements crypto.PubKey for the Ed25519 signature scheme.
type PubKey []byte
// TypeTag satisfies the jsontypes.Tagged interface.
func (PubKey) TypeTag() string { return PubKeyName }
// Address is the SHA256-20 of the raw pubkey bytes.
func (pubKey PubKey) Address() crypto.Address {
if len(pubKey) != PubKeySize {

View File

@@ -10,6 +10,7 @@ import (
secp256k1 "github.com/btcsuite/btcd/btcec"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/internal/jsontypes"
tmjson "github.com/tendermint/tendermint/libs/json"
// necessary for Bitcoin address format
@@ -28,6 +29,9 @@ const (
func init() {
tmjson.RegisterType(PubKey{}, PubKeyName)
tmjson.RegisterType(PrivKey{}, PrivKeyName)
jsontypes.MustRegister(PubKey{})
jsontypes.MustRegister(PrivKey{})
}
var _ crypto.PrivKey = PrivKey{}
@@ -35,6 +39,9 @@ var _ crypto.PrivKey = PrivKey{}
// PrivKey implements PrivKey.
type PrivKey []byte
// TypeTag satisfies the jsontypes.Tagged interface.
func (PrivKey) TypeTag() string { return PrivKeyName }
// Bytes marshalls the private key using amino encoding.
func (privKey PrivKey) Bytes() []byte {
return []byte(privKey)
@@ -138,6 +145,9 @@ const PubKeySize = 33
// This prefix is followed with the x-coordinate.
type PubKey []byte
// TypeTag satisfies the jsontypes.Tagged interface.
func (PubKey) TypeTag() string { return PubKeyName }
// Address returns a Bitcoin style addresses: RIPEMD160(SHA256(pubkey))
func (pubKey PubKey) Address() crypto.Address {
if len(pubKey) != PubKeySize {

View File

@@ -1,6 +1,9 @@
package sr25519
import tmjson "github.com/tendermint/tendermint/libs/json"
import (
"github.com/tendermint/tendermint/internal/jsontypes"
tmjson "github.com/tendermint/tendermint/libs/json"
)
const (
PrivKeyName = "tendermint/PrivKeySr25519"
@@ -10,4 +13,7 @@ const (
func init() {
tmjson.RegisterType(PubKey{}, PubKeyName)
tmjson.RegisterType(PrivKey{}, PrivKeyName)
jsontypes.MustRegister(PubKey{})
jsontypes.MustRegister(PrivKey{})
}

View File

@@ -29,6 +29,9 @@ type PrivKey struct {
kp *sr25519.KeyPair
}
// TypeTag satisfies the jsontypes.Tagged interface.
func (PrivKey) TypeTag() string { return PrivKeyName }
// Bytes returns the byte-encoded PrivKey.
func (privKey PrivKey) Bytes() []byte {
if privKey.kp == nil {

View File

@@ -23,6 +23,9 @@ const (
// PubKey implements crypto.PubKey.
type PubKey []byte
// TypeTag satisfies the jsontypes.Tagged interface.
func (PubKey) TypeTag() string { return PubKeyName }
// Address is the SHA256-20 of the raw pubkey bytes.
func (pubKey PubKey) Address() crypto.Address {
if len(pubKey) != PubKeySize {