Browse Source

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.
pull/7606/head
M. J. Fromberger 3 years ago
committed by GitHub
parent
commit
dbe2146d0a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 349 additions and 24 deletions
  1. +7
    -0
      crypto/crypto.go
  2. +10
    -0
      crypto/ed25519/ed25519.go
  3. +10
    -0
      crypto/secp256k1/secp256k1.go
  4. +7
    -1
      crypto/sr25519/encoding.go
  5. +3
    -0
      crypto/sr25519/privkey.go
  6. +3
    -0
      crypto/sr25519/pubkey.go
  7. +109
    -0
      internal/jsontypes/jsontypes.go
  8. +83
    -0
      internal/jsontypes/jsontypes_test.go
  9. +1
    -0
      internal/p2p/conn/secret_connection_test.go
  10. +17
    -0
      privval/file.go
  11. +3
    -1
      rpc/client/http/http.go
  12. +20
    -0
      rpc/client/http/request.go
  13. +2
    -2
      types/block.go
  14. +21
    -8
      types/evidence.go
  15. +15
    -1
      types/genesis.go
  16. +17
    -4
      types/node_key.go
  17. +18
    -4
      types/validator.go
  18. +1
    -1
      types/vote.go
  19. +2
    -2
      version/version.go

+ 7
- 0
crypto/crypto.go View File

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


+ 10
- 0
crypto/ed25519/ed25519.go View File

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


+ 10
- 0
crypto/secp256k1/secp256k1.go View File

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


+ 7
- 1
crypto/sr25519/encoding.go View File

@ -1,6 +1,9 @@
package sr25519 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 ( const (
PrivKeyName = "tendermint/PrivKeySr25519" PrivKeyName = "tendermint/PrivKeySr25519"
@ -10,4 +13,7 @@ const (
func init() { func init() {
tmjson.RegisterType(PubKey{}, PubKeyName) tmjson.RegisterType(PubKey{}, PubKeyName)
tmjson.RegisterType(PrivKey{}, PrivKeyName) tmjson.RegisterType(PrivKey{}, PrivKeyName)
jsontypes.MustRegister(PubKey{})
jsontypes.MustRegister(PrivKey{})
} }

+ 3
- 0
crypto/sr25519/privkey.go View File

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


+ 3
- 0
crypto/sr25519/pubkey.go View File

@ -23,6 +23,9 @@ const (
// PubKey implements crypto.PubKey. // PubKey implements crypto.PubKey.
type PubKey []byte 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. // Address is the SHA256-20 of the raw pubkey bytes.
func (pubKey PubKey) Address() crypto.Address { func (pubKey PubKey) Address() crypto.Address {
if len(pubKey) != PubKeySize { if len(pubKey) != PubKeySize {


+ 109
- 0
internal/jsontypes/jsontypes.go View File

@ -0,0 +1,109 @@
// Package jsontypes supports decoding for interface types whose concrete
// implementations need to be stored as JSON. To do this, concrete values are
// packaged in wrapper objects having the form:
//
// {
// "type": "<type-tag>",
// "value": <json-encoding-of-value>
// }
//
// This package provides a registry for type tag strings and functions to
// encode and decode wrapper objects.
package jsontypes
import (
"bytes"
"encoding/json"
"fmt"
"reflect"
)
// The Tagged interface must be implemented by a type in order to register it
// with the jsontypes package. The TypeTag method returns a string label that
// is used to distinguish objects of that type.
type Tagged interface {
TypeTag() string
}
// registry records the mapping from type tags to value types. Values in this
// map must be normalized to non-pointer types.
var registry = struct {
types map[string]reflect.Type
}{types: make(map[string]reflect.Type)}
// register adds v to the type registry. It reports an error if the tag
// returned by v is already registered.
func register(v Tagged) error {
tag := v.TypeTag()
if t, ok := registry.types[tag]; ok {
return fmt.Errorf("type tag %q already registered to %v", tag, t)
}
typ := reflect.TypeOf(v)
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}
registry.types[tag] = typ
return nil
}
// MustRegister adds v to the type registry. It will panic if the tag returned
// by v is already registered. This function is meant for use during program
// initialization.
func MustRegister(v Tagged) {
if err := register(v); err != nil {
panic(err)
}
}
type wrapper struct {
Type string `json:"type"`
Value json.RawMessage `json:"value"`
}
// Marshal marshals a JSON wrapper object containing v. If v == nil, Marshal
// returns the JSON "null" value without error.
func Marshal(v Tagged) ([]byte, error) {
if v == nil {
return []byte("null"), nil
}
data, err := json.Marshal(v)
if err != nil {
return nil, err
}
return json.Marshal(wrapper{
Type: v.TypeTag(),
Value: data,
})
}
// Unmarshal unmarshals a JSON wrapper object into v. It reports an error if
// the data do not encode a valid wrapper object, if the wrapper's type tag is
// not registered with jsontypes, or if the resulting value is not compatible
// with the type of v.
func Unmarshal(data []byte, v interface{}) error {
// Verify that the target is some kind of pointer.
target := reflect.ValueOf(v)
if target.Kind() != reflect.Ptr {
return fmt.Errorf("target %T is not a pointer", v)
}
var w wrapper
dec := json.NewDecoder(bytes.NewReader(data))
dec.DisallowUnknownFields()
if err := dec.Decode(&w); err != nil {
return fmt.Errorf("invalid type wrapper: %w", err)
}
typ, ok := registry.types[w.Type]
if !ok {
return fmt.Errorf("unknown type tag: %q", w.Type)
} else if !typ.AssignableTo(target.Elem().Type()) {
return fmt.Errorf("type %v not assignable to %T", typ, v)
}
obj := reflect.New(typ)
if err := json.Unmarshal(w.Value, obj.Interface()); err != nil {
return fmt.Errorf("decoding wrapped value: %w", err)
}
target.Elem().Set(obj.Elem())
return nil
}

+ 83
- 0
internal/jsontypes/jsontypes_test.go View File

@ -0,0 +1,83 @@
package jsontypes_test
import (
"testing"
"github.com/tendermint/tendermint/internal/jsontypes"
)
type testType struct {
Field string `json:"field"`
}
func (*testType) TypeTag() string { return "test/TaggedType" }
func TestRoundTrip(t *testing.T) {
const wantEncoded = `{"type":"test/TaggedType","value":{"field":"hello"}}`
t.Run("MustRegisterOK", func(t *testing.T) {
defer func() {
if x := recover(); x != nil {
t.Fatalf("Registration panicked: %v", x)
}
}()
jsontypes.MustRegister((*testType)(nil))
})
t.Run("MustRegisterFail", func(t *testing.T) {
defer func() {
if x := recover(); x != nil {
t.Logf("Got expected panic: %v", x)
}
}()
jsontypes.MustRegister((*testType)(nil))
t.Fatal("Registration should not have succeeded")
})
t.Run("MarshalNil", func(t *testing.T) {
bits, err := jsontypes.Marshal(nil)
if err != nil {
t.Fatalf("Marshal failed: %v", err)
}
if got := string(bits); got != "null" {
t.Errorf("Marshal nil: got %#q, want null", got)
}
})
t.Run("RoundTrip", func(t *testing.T) {
obj := testType{Field: "hello"}
bits, err := jsontypes.Marshal(&obj)
if err != nil {
t.Fatalf("Marshal %T failed: %v", obj, err)
}
if got := string(bits); got != wantEncoded {
t.Errorf("Marshal %T: got %#q, want %#q", obj, got, wantEncoded)
}
var cmp testType
if err := jsontypes.Unmarshal(bits, &cmp); err != nil {
t.Errorf("Unmarshal %#q failed: %v", string(bits), err)
}
if obj != cmp {
t.Errorf("Unmarshal %#q: got %+v, want %+v", string(bits), cmp, obj)
}
})
t.Run("Unregistered", func(t *testing.T) {
obj := testType{Field: "hello"}
bits, err := jsontypes.Marshal(&obj)
if err != nil {
t.Fatalf("Marshal %T failed: %v", obj, err)
}
if got := string(bits); got != wantEncoded {
t.Errorf("Marshal %T: got %#q, want %#q", obj, got, wantEncoded)
}
var cmp struct {
Field string `json:"field"`
}
if err := jsontypes.Unmarshal(bits, &cmp); err != nil {
t.Errorf("Unmarshal %#q: got %+v, want %+v", string(bits), cmp, obj)
}
})
}

+ 1
- 0
internal/p2p/conn/secret_connection_test.go View File

@ -52,6 +52,7 @@ func (pk privKeyWithNilPubKey) Sign(msg []byte) ([]byte, error) { return pk.orig
func (pk privKeyWithNilPubKey) PubKey() crypto.PubKey { return nil } func (pk privKeyWithNilPubKey) PubKey() crypto.PubKey { return nil }
func (pk privKeyWithNilPubKey) Equals(pk2 crypto.PrivKey) bool { return pk.orig.Equals(pk2) } func (pk privKeyWithNilPubKey) Equals(pk2 crypto.PrivKey) bool { return pk.orig.Equals(pk2) }
func (pk privKeyWithNilPubKey) Type() string { return "privKeyWithNilPubKey" } func (pk privKeyWithNilPubKey) Type() string { return "privKeyWithNilPubKey" }
func (privKeyWithNilPubKey) TypeTag() string { return "test/privKeyWithNilPubKey" }
func TestSecretConnectionHandshake(t *testing.T) { func TestSecretConnectionHandshake(t *testing.T) {
fooSecConn, barSecConn := makeSecretConnPair(t) fooSecConn, barSecConn := makeSecretConnPair(t)


+ 17
- 0
privval/file.go View File

@ -14,6 +14,7 @@ import (
"github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/secp256k1" "github.com/tendermint/tendermint/crypto/secp256k1"
"github.com/tendermint/tendermint/internal/jsontypes"
"github.com/tendermint/tendermint/internal/libs/protoio" "github.com/tendermint/tendermint/internal/libs/protoio"
"github.com/tendermint/tendermint/internal/libs/tempfile" "github.com/tendermint/tendermint/internal/libs/tempfile"
tmbytes "github.com/tendermint/tendermint/libs/bytes" tmbytes "github.com/tendermint/tendermint/libs/bytes"
@ -55,6 +56,22 @@ type FilePVKey struct {
filePath string filePath string
} }
func (pvKey FilePVKey) MarshalJSON() ([]byte, error) {
pubk, err := jsontypes.Marshal(pvKey.PubKey)
if err != nil {
return nil, err
}
privk, err := jsontypes.Marshal(pvKey.PrivKey)
if err != nil {
return nil, err
}
return json.Marshal(struct {
Address types.Address `json:"address"`
PubKey json.RawMessage `json:"pub_key"`
PrivKey json.RawMessage `json:"priv_key"`
}{Address: pvKey.Address, PubKey: pubk, PrivKey: privk})
}
// Save persists the FilePVKey to its filePath. // Save persists the FilePVKey to its filePath.
func (pvKey FilePVKey) Save() error { func (pvKey FilePVKey) Save() error {
outFile := pvKey.filePath outFile := pvKey.filePath


+ 3
- 1
rpc/client/http/http.go View File

@ -510,7 +510,9 @@ func (c *baseRPCClient) BroadcastEvidence(
ev types.Evidence, ev types.Evidence,
) (*coretypes.ResultBroadcastEvidence, error) { ) (*coretypes.ResultBroadcastEvidence, error) {
result := new(coretypes.ResultBroadcastEvidence) result := new(coretypes.ResultBroadcastEvidence)
if err := c.caller.Call(ctx, "broadcast_evidence", map[string]interface{}{"evidence": ev}, result); err != nil {
if err := c.caller.Call(ctx, "broadcast_evidence", evidenceArgs{
Evidence: ev,
}, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil


+ 20
- 0
rpc/client/http/request.go View File

@ -4,7 +4,11 @@ package http
// from the client to the server. // from the client to the server.
import ( import (
"encoding/json"
"github.com/tendermint/tendermint/internal/jsontypes"
"github.com/tendermint/tendermint/libs/bytes" "github.com/tendermint/tendermint/libs/bytes"
"github.com/tendermint/tendermint/types"
) )
type abciQueryArgs struct { type abciQueryArgs struct {
@ -57,3 +61,19 @@ type validatorArgs struct {
Page *int `json:"page,string,omitempty"` Page *int `json:"page,string,omitempty"`
PerPage *int `json:"per_page,string,omitempty"` PerPage *int `json:"per_page,string,omitempty"`
} }
type evidenceArgs struct {
Evidence types.Evidence
}
// MarshalJSON implements json.Marshaler to encode the evidence using the
// wrapped concrete type of the implementation.
func (e evidenceArgs) MarshalJSON() ([]byte, error) {
ev, err := jsontypes.Marshal(e.Evidence)
if err != nil {
return nil, err
}
return json.Marshal(struct {
Evidence json.RawMessage `json:"evidence"`
}{Evidence: ev})
}

+ 2
- 2
types/block.go View File

@ -334,7 +334,7 @@ type Header struct {
// basic block info // basic block info
Version version.Consensus `json:"version"` Version version.Consensus `json:"version"`
ChainID string `json:"chain_id"` ChainID string `json:"chain_id"`
Height int64 `json:"height"`
Height int64 `json:"height,string"`
Time time.Time `json:"time"` Time time.Time `json:"time"`
// prev block info // prev block info
@ -748,7 +748,7 @@ type Commit struct {
// ValidatorSet order. // ValidatorSet order.
// Any peer with a block can gossip signatures by index with a peer without // Any peer with a block can gossip signatures by index with a peer without
// recalculating the active ValidatorSet. // recalculating the active ValidatorSet.
Height int64 `json:"height"`
Height int64 `json:"height,string"`
Round int32 `json:"round"` Round int32 `json:"round"`
BlockID BlockID `json:"block_id"` BlockID BlockID `json:"block_id"`
Signatures []CommitSig `json:"signatures"` Signatures []CommitSig `json:"signatures"`


+ 21
- 8
types/evidence.go View File

@ -13,6 +13,7 @@ import (
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/merkle" "github.com/tendermint/tendermint/crypto/merkle"
"github.com/tendermint/tendermint/crypto/tmhash" "github.com/tendermint/tendermint/crypto/tmhash"
"github.com/tendermint/tendermint/internal/jsontypes"
tmjson "github.com/tendermint/tendermint/libs/json" tmjson "github.com/tendermint/tendermint/libs/json"
tmrand "github.com/tendermint/tendermint/libs/rand" tmrand "github.com/tendermint/tendermint/libs/rand"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
@ -28,6 +29,9 @@ type Evidence interface {
String() string // string format of the evidence String() string // string format of the evidence
Time() time.Time // time of the infraction Time() time.Time // time of the infraction
ValidateBasic() error // basic consistency check ValidateBasic() error // basic consistency check
// Implementations must support tagged encoding in JSON.
jsontypes.Tagged
} }
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -38,11 +42,14 @@ type DuplicateVoteEvidence struct {
VoteB *Vote `json:"vote_b"` VoteB *Vote `json:"vote_b"`
// abci specific information // abci specific information
TotalVotingPower int64
ValidatorPower int64
TotalVotingPower int64 `json:",string"`
ValidatorPower int64 `json:",string"`
Timestamp time.Time Timestamp time.Time
} }
// TypeTag implements the jsontypes.Tagged interface.
func (*DuplicateVoteEvidence) TypeTag() string { return "tendermint/DuplicateVoteEvidence" }
var _ Evidence = &DuplicateVoteEvidence{} var _ Evidence = &DuplicateVoteEvidence{}
// NewDuplicateVoteEvidence creates DuplicateVoteEvidence with right ordering given // NewDuplicateVoteEvidence creates DuplicateVoteEvidence with right ordering given
@ -236,14 +243,17 @@ func DuplicateVoteEvidenceFromProto(pb *tmproto.DuplicateVoteEvidence) (*Duplica
// height, then nodes will treat this as of the Lunatic form, else it is of the Equivocation form. // height, then nodes will treat this as of the Lunatic form, else it is of the Equivocation form.
type LightClientAttackEvidence struct { type LightClientAttackEvidence struct {
ConflictingBlock *LightBlock ConflictingBlock *LightBlock
CommonHeight int64
CommonHeight int64 `json:",string"`
// abci specific information // abci specific information
ByzantineValidators []*Validator // validators in the validator set that misbehaved in creating the conflicting block ByzantineValidators []*Validator // validators in the validator set that misbehaved in creating the conflicting block
TotalVotingPower int64 // total voting power of the validator set at the common height
TotalVotingPower int64 `json:",string"` // total voting power of the validator set at the common height
Timestamp time.Time // timestamp of the block at the common height Timestamp time.Time // timestamp of the block at the common height
} }
// TypeTag implements the jsontypes.Tagged interface.
func (*LightClientAttackEvidence) TypeTag() string { return "tendermint/LightClientAttackEvidence" }
var _ Evidence = &LightClientAttackEvidence{} var _ Evidence = &LightClientAttackEvidence{}
// ABCI forms an array of abci evidence for each byzantine validator // ABCI forms an array of abci evidence for each byzantine validator
@ -365,10 +375,10 @@ func (l *LightClientAttackEvidence) Height() int64 {
// String returns a string representation of LightClientAttackEvidence // String returns a string representation of LightClientAttackEvidence
func (l *LightClientAttackEvidence) String() string { func (l *LightClientAttackEvidence) String() string {
return fmt.Sprintf(`LightClientAttackEvidence{ return fmt.Sprintf(`LightClientAttackEvidence{
ConflictingBlock: %v,
CommonHeight: %d,
ByzatineValidators: %v,
TotalVotingPower: %d,
ConflictingBlock: %v,
CommonHeight: %d,
ByzatineValidators: %v,
TotalVotingPower: %d,
Timestamp: %v}#%X`, Timestamp: %v}#%X`,
l.ConflictingBlock.String(), l.CommonHeight, l.ByzantineValidators, l.ConflictingBlock.String(), l.CommonHeight, l.ByzantineValidators,
l.TotalVotingPower, l.Timestamp, l.Hash()) l.TotalVotingPower, l.Timestamp, l.Hash())
@ -630,6 +640,9 @@ func EvidenceFromProto(evidence *tmproto.Evidence) (Evidence, error) {
func init() { func init() {
tmjson.RegisterType(&DuplicateVoteEvidence{}, "tendermint/DuplicateVoteEvidence") tmjson.RegisterType(&DuplicateVoteEvidence{}, "tendermint/DuplicateVoteEvidence")
tmjson.RegisterType(&LightClientAttackEvidence{}, "tendermint/LightClientAttackEvidence") tmjson.RegisterType(&LightClientAttackEvidence{}, "tendermint/LightClientAttackEvidence")
jsontypes.MustRegister((*DuplicateVoteEvidence)(nil))
jsontypes.MustRegister((*LightClientAttackEvidence)(nil))
} }
//-------------------------------------------- ERRORS -------------------------------------- //-------------------------------------------- ERRORS --------------------------------------


+ 15
- 1
types/genesis.go View File

@ -9,6 +9,7 @@ import (
"time" "time"
"github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/internal/jsontypes"
tmbytes "github.com/tendermint/tendermint/libs/bytes" tmbytes "github.com/tendermint/tendermint/libs/bytes"
tmjson "github.com/tendermint/tendermint/libs/json" tmjson "github.com/tendermint/tendermint/libs/json"
tmtime "github.com/tendermint/tendermint/libs/time" tmtime "github.com/tendermint/tendermint/libs/time"
@ -29,10 +30,23 @@ const (
type GenesisValidator struct { type GenesisValidator struct {
Address Address `json:"address"` Address Address `json:"address"`
PubKey crypto.PubKey `json:"pub_key"` PubKey crypto.PubKey `json:"pub_key"`
Power int64 `json:"power"`
Power int64 `json:"power,string"`
Name string `json:"name"` Name string `json:"name"`
} }
func (g GenesisValidator) MarshalJSON() ([]byte, error) {
pk, err := jsontypes.Marshal(g.PubKey)
if err != nil {
return nil, err
}
return json.Marshal(struct {
Address Address `json:"address"`
PubKey json.RawMessage `json:"pub_key"`
Power int64 `json:"power,string"`
Name string `json:"name"`
}{Address: g.Address, PubKey: pk, Power: g.Power, Name: g.Name})
}
// GenesisDoc defines the initial conditions for a tendermint blockchain, in particular its validator set. // GenesisDoc defines the initial conditions for a tendermint blockchain, in particular its validator set.
type GenesisDoc struct { type GenesisDoc struct {
GenesisTime time.Time `json:"genesis_time"` GenesisTime time.Time `json:"genesis_time"`


+ 17
- 4
types/node_key.go View File

@ -1,10 +1,12 @@
package types package types
import ( import (
"encoding/json"
"os" "os"
"github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/internal/jsontypes"
tmjson "github.com/tendermint/tendermint/libs/json" tmjson "github.com/tendermint/tendermint/libs/json"
tmos "github.com/tendermint/tendermint/libs/os" tmos "github.com/tendermint/tendermint/libs/os"
) )
@ -22,14 +24,25 @@ type NodeKey struct {
PrivKey crypto.PrivKey `json:"priv_key"` PrivKey crypto.PrivKey `json:"priv_key"`
} }
func (nk NodeKey) MarshalJSON() ([]byte, error) {
pk, err := jsontypes.Marshal(nk.PrivKey)
if err != nil {
return nil, err
}
return json.Marshal(struct {
ID NodeID `json:"id"`
PrivKey json.RawMessage `json:"priv_key"`
}{ID: nk.ID, PrivKey: pk})
}
// PubKey returns the peer's PubKey // PubKey returns the peer's PubKey
func (nodeKey NodeKey) PubKey() crypto.PubKey {
return nodeKey.PrivKey.PubKey()
func (nk NodeKey) PubKey() crypto.PubKey {
return nk.PrivKey.PubKey()
} }
// SaveAs persists the NodeKey to filePath. // SaveAs persists the NodeKey to filePath.
func (nodeKey NodeKey) SaveAs(filePath string) error {
jsonBytes, err := tmjson.Marshal(nodeKey)
func (nk NodeKey) SaveAs(filePath string) error {
jsonBytes, err := tmjson.Marshal(nk)
if err != nil { if err != nil {
return err return err
} }


+ 18
- 4
types/validator.go View File

@ -2,12 +2,14 @@ package types
import ( import (
"bytes" "bytes"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"strings" "strings"
"github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/encoding" "github.com/tendermint/tendermint/crypto/encoding"
"github.com/tendermint/tendermint/internal/jsontypes"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
) )
@ -15,11 +17,23 @@ import (
// NOTE: The ProposerPriority is not included in Validator.Hash(); // NOTE: The ProposerPriority is not included in Validator.Hash();
// make sure to update that method if changes are made here // make sure to update that method if changes are made here
type Validator struct { type Validator struct {
Address Address `json:"address"`
PubKey crypto.PubKey `json:"pub_key"`
VotingPower int64 `json:"voting_power"`
Address Address `json:"address"`
PubKey crypto.PubKey `json:"pub_key"`
VotingPower int64 `json:"voting_power,string"`
ProposerPriority int64 `json:"proposer_priority,string"`
}
ProposerPriority int64 `json:"proposer_priority"`
func (v Validator) MarshalJSON() ([]byte, error) {
pk, err := jsontypes.Marshal(v.PubKey)
if err != nil {
return nil, err
}
return json.Marshal(struct {
Addr Address `json:"address"`
PubKey json.RawMessage `json:"pub_key"`
Power int64 `json:"voting_power,string"`
Priority int64 `json:"proposer_priority,string"`
}{Addr: v.Address, PubKey: pk, Power: v.VotingPower, Priority: v.ProposerPriority})
} }
// NewValidator returns a new validator with the given pubkey and voting power. // NewValidator returns a new validator with the given pubkey and voting power.


+ 1
- 1
types/vote.go View File

@ -49,7 +49,7 @@ type Address = crypto.Address
// consensus. // consensus.
type Vote struct { type Vote struct {
Type tmproto.SignedMsgType `json:"type"` Type tmproto.SignedMsgType `json:"type"`
Height int64 `json:"height"`
Height int64 `json:"height,string"`
Round int32 `json:"round"` // assume there will not be greater than 2_147_483_647 rounds Round int32 `json:"round"` // assume there will not be greater than 2_147_483_647 rounds
BlockID BlockID `json:"block_id"` // zero if vote is nil. BlockID BlockID `json:"block_id"` // zero if vote is nil.
Timestamp time.Time `json:"timestamp"` Timestamp time.Time `json:"timestamp"`


+ 2
- 2
version/version.go View File

@ -28,8 +28,8 @@ var (
) )
type Consensus struct { type Consensus struct {
Block uint64 `json:"block"`
App uint64 `json:"app"`
Block uint64 `json:"block,string"`
App uint64 `json:"app,string"`
} }
func (c Consensus) ToProto() tmversion.Consensus { func (c Consensus) ToProto() tmversion.Consensus {


Loading…
Cancel
Save