proto: add proto files for ibc unblock (#4853) (#4906)

these proto files are meant to help unblock ibc in their quest of migrating the ibc module to proto.
This commit is contained in:
Marko
2020-05-28 12:41:32 +02:00
committed by Tess Rinearson
parent 64c7771966
commit d9c2f01bb5
59 changed files with 8914 additions and 13 deletions
+229 -10
View File
@@ -15,6 +15,8 @@ import (
"github.com/tendermint/tendermint/libs/bits"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
tmmath "github.com/tendermint/tendermint/libs/math"
tmproto "github.com/tendermint/tendermint/proto/types"
tmversion "github.com/tendermint/tendermint/proto/version"
"github.com/tendermint/tendermint/version"
)
@@ -450,6 +452,62 @@ func (h *Header) StringIndented(indent string) string {
indent, h.Hash())
}
// ToProto converts Header to protobuf
func (h *Header) ToProto() *tmproto.Header {
if h == nil {
return nil
}
return &tmproto.Header{
Version: tmversion.Consensus{Block: h.Version.App.Uint64(), App: h.Version.App.Uint64()},
ChainID: h.ChainID,
Height: h.Height,
Time: h.Time,
LastBlockID: h.LastBlockID.ToProto(),
ValidatorsHash: h.ValidatorsHash,
NextValidatorsHash: h.NextValidatorsHash,
ConsensusHash: h.ConsensusHash,
AppHash: h.AppHash,
DataHash: h.DataHash,
EvidenceHash: h.EvidenceHash,
LastResultsHash: h.LastResultsHash,
LastCommitHash: h.LastCommitHash,
ProposerAddress: h.ProposerAddress,
}
}
// FromProto sets a protobuf Header to the given pointer.
// It returns an error if the header is invalid.
func HeaderFromProto(ph *tmproto.Header) (Header, error) {
if ph == nil {
return Header{}, errors.New("nil Header")
}
h := new(Header)
bi, err := BlockIDFromProto(&ph.LastBlockID)
if err != nil {
return Header{}, err
}
h.Version = version.Consensus{Block: version.Protocol(ph.Version.Block), App: version.Protocol(ph.Version.App)}
h.ChainID = ph.ChainID
h.Height = ph.Height
h.Time = ph.Time
h.Height = ph.Height
h.LastBlockID = *bi
h.ValidatorsHash = ph.ValidatorsHash
h.NextValidatorsHash = ph.NextValidatorsHash
h.ConsensusHash = ph.ConsensusHash
h.AppHash = ph.AppHash
h.DataHash = ph.DataHash
h.EvidenceHash = ph.EvidenceHash
h.LastResultsHash = ph.LastResultsHash
h.LastCommitHash = ph.LastCommitHash
h.ProposerAddress = ph.ProposerAddress
return *h, h.ValidateBasic()
}
//-------------------------------------
// BlockIDFlag indicates which BlockID the signature is for.
@@ -565,6 +623,32 @@ func (cs CommitSig) ValidateBasic() error {
return nil
}
// ToProto converts CommitSig to protobuf
func (cs *CommitSig) ToProto() *tmproto.CommitSig {
if cs == nil {
return nil
}
return &tmproto.CommitSig{
BlockIdFlag: tmproto.BlockIDFlag(cs.BlockIDFlag),
ValidatorAddress: cs.ValidatorAddress,
Timestamp: cs.Timestamp,
Signature: cs.Signature,
}
}
// FromProto sets a protobuf CommitSig to the given pointer.
// It returns an error if the CommitSig is invalid.
func (cs *CommitSig) FromProto(csp tmproto.CommitSig) error {
cs.BlockIDFlag = BlockIDFlag(csp.BlockIdFlag)
cs.ValidatorAddress = csp.ValidatorAddress
cs.Timestamp = csp.Timestamp
cs.Signature = csp.Signature
return cs.ValidateBasic()
}
//-------------------------------------
// Commit contains the evidence that a block was committed by a set of validators.
@@ -701,17 +785,18 @@ func (commit *Commit) ValidateBasic() error {
if commit.Round < 0 {
return errors.New("negative Round")
}
if commit.Height >= 1 {
if commit.BlockID.IsZero() {
return errors.New("commit cannot be for nil block")
}
if commit.BlockID.IsZero() {
return errors.New("commit cannot be for nil block")
}
if len(commit.Signatures) == 0 {
return errors.New("no signatures in commit")
}
for i, commitSig := range commit.Signatures {
if err := commitSig.ValidateBasic(); err != nil {
return fmt.Errorf("wrong CommitSig #%d: %v", i, err)
if len(commit.Signatures) == 0 {
return errors.New("no signatures in commit")
}
for i, commitSig := range commit.Signatures {
if err := commitSig.ValidateBasic(); err != nil {
return fmt.Errorf("wrong CommitSig #%d: %v", i, err)
}
}
}
@@ -757,6 +842,65 @@ func (commit *Commit) StringIndented(indent string) string {
indent, commit.hash)
}
// ToProto converts Commit to protobuf
func (commit *Commit) ToProto() *tmproto.Commit {
if commit == nil {
return nil
}
c := new(tmproto.Commit)
sigs := make([]tmproto.CommitSig, len(commit.Signatures))
for i := range commit.Signatures {
sigs[i] = *commit.Signatures[i].ToProto()
}
c.Signatures = sigs
c.Height = commit.Height
c.Round = int32(commit.Round)
c.BlockID = commit.BlockID.ToProto()
if commit.hash != nil {
c.Hash = commit.hash
}
c.BitArray = commit.bitArray.ToProto()
return c
}
// FromProto sets a protobuf Commit to the given pointer.
// It returns an error if the commit is invalid.
func CommitFromProto(cp *tmproto.Commit) (*Commit, error) {
if cp == nil {
return nil, errors.New("nil Commit")
}
var (
commit = new(Commit)
bitArray *bits.BitArray
)
bi, err := BlockIDFromProto(&cp.BlockID)
if err != nil {
return nil, err
}
bitArray.FromProto(cp.BitArray)
sigs := make([]CommitSig, len(cp.Signatures))
for i := range cp.Signatures {
if err := sigs[i].FromProto(cp.Signatures[i]); err != nil {
return nil, err
}
}
commit.Signatures = sigs
commit.Height = cp.Height
commit.Round = int(cp.Round)
commit.BlockID = *bi
commit.hash = cp.Hash
commit.bitArray = bitArray
return commit, commit.ValidateBasic()
}
//-----------------------------------------------------------------------------
// SignedHeader is a header along with the commits that prove it.
@@ -816,6 +960,51 @@ func (sh SignedHeader) StringIndented(indent string) string {
indent)
}
// ToProto converts SignedHeader to protobuf
func (sh *SignedHeader) ToProto() *tmproto.SignedHeader {
if sh == nil {
return nil
}
psh := new(tmproto.SignedHeader)
if sh.Header != nil {
psh.Header = sh.Header.ToProto()
}
if sh.Commit != nil {
psh.Commit = sh.Commit.ToProto()
}
return psh
}
// FromProto sets a protobuf SignedHeader to the given pointer.
// It returns an error if the hader or the commit is invalid.
func SignedHeaderFromProto(shp *tmproto.SignedHeader) (*SignedHeader, error) {
if shp == nil {
return nil, errors.New("nil SignedHeader")
}
sh := new(SignedHeader)
if shp.Header != nil {
h, err := HeaderFromProto(shp.Header)
if err != nil {
return nil, err
}
sh.Header = &h
}
if shp.Commit != nil {
c, err := CommitFromProto(shp.Commit)
if err != nil {
return nil, err
}
sh.Commit = c
}
return sh, nil
}
//-----------------------------------------------------------------------------
// Data contains the set of transactions included in the block
@@ -951,3 +1140,33 @@ func (blockID BlockID) IsComplete() bool {
func (blockID BlockID) String() string {
return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartsHeader)
}
// ToProto converts BlockID to protobuf
func (blockID *BlockID) ToProto() tmproto.BlockID {
if blockID == nil {
return tmproto.BlockID{}
}
return tmproto.BlockID{
Hash: blockID.Hash,
PartsHeader: blockID.PartsHeader.ToProto(),
}
}
// FromProto sets a protobuf BlockID to the given pointer.
// It returns an error if the block id is invalid.
func BlockIDFromProto(bID *tmproto.BlockID) (*BlockID, error) {
if bID == nil {
return nil, errors.New("nil BlockID")
}
blockID := new(BlockID)
ph, err := PartSetHeaderFromProto(&bID.PartsHeader)
if err != nil {
return nil, err
}
blockID.PartsHeader = *ph
blockID.Hash = bID.Hash
return blockID, blockID.ValidateBasic()
}
+136
View File
@@ -598,3 +598,139 @@ func TestBlockIDValidateBasic(t *testing.T) {
})
}
}
func makeRandHeader() Header {
chainID := "test"
t := time.Now()
height := tmrand.Int63()
randBytes := tmrand.Bytes(tmhash.Size)
randAddress := tmrand.Bytes(crypto.AddressSize)
h := Header{
Version: version.Consensus{Block: 1, App: 1},
ChainID: chainID,
Height: height,
Time: t,
LastBlockID: BlockID{},
LastCommitHash: randBytes,
DataHash: randBytes,
ValidatorsHash: randBytes,
NextValidatorsHash: randBytes,
ConsensusHash: randBytes,
AppHash: randBytes,
LastResultsHash: randBytes,
EvidenceHash: randBytes,
ProposerAddress: randAddress,
}
return h
}
func TestHeaderProto(t *testing.T) {
h1 := makeRandHeader()
tc := []struct {
msg string
h1 *Header
expPass bool
}{
{"success", &h1, true},
{"failure empty Header", &Header{}, false},
}
for _, tt := range tc {
tt := tt
t.Run(tt.msg, func(t *testing.T) {
pb := tt.h1.ToProto()
h, err := HeaderFromProto(pb)
if tt.expPass {
require.NoError(t, err, tt.msg)
require.Equal(t, tt.h1, &h, tt.msg)
} else {
require.Error(t, err, tt.msg)
}
})
}
}
func TestBlockIDProtoBuf(t *testing.T) {
blockID := makeBlockID([]byte("hash"), 2, []byte("part_set_hash"))
testCases := []struct {
msg string
bid1 *BlockID
expPass bool
}{
{"success", &blockID, true},
{"success empty", &BlockID{}, true},
{"failure BlockID nil", nil, false},
}
for _, tc := range testCases {
protoBlockID := tc.bid1.ToProto()
bi, err := BlockIDFromProto(&protoBlockID)
if tc.expPass {
require.NoError(t, err)
require.Equal(t, tc.bid1, bi, tc.msg)
} else {
require.NotEqual(t, tc.bid1, bi, tc.msg)
}
}
}
func TestSignedHeaderProtoBuf(t *testing.T) {
commit := randCommit(time.Now())
h := makeRandHeader()
sh := SignedHeader{Header: &h, Commit: commit}
testCases := []struct {
msg string
sh1 *SignedHeader
expPass bool
}{
{"empty SignedHeader 2", &SignedHeader{}, true},
{"success", &sh, true},
{"failure nil", nil, false},
}
for _, tc := range testCases {
protoSignedHeader := tc.sh1.ToProto()
sh, err := SignedHeaderFromProto(protoSignedHeader)
if tc.expPass {
require.NoError(t, err, tc.msg)
require.Equal(t, tc.sh1, sh, tc.msg)
} else {
require.Error(t, err, tc.msg)
}
}
}
func TestCommitProtoBuf(t *testing.T) {
commit := randCommit(time.Now())
testCases := []struct {
msg string
c1 *Commit
expPass bool
}{
{"success", commit, true},
// Empty value sets signatures to nil, signatures should not be nillable
{"empty commit", &Commit{Signatures: []CommitSig{}}, true},
{"fail Commit nil", nil, false},
}
for _, tc := range testCases {
tc := tc
protoCommit := tc.c1.ToProto()
c, err := CommitFromProto(protoCommit)
if tc.expPass {
require.NoError(t, err, tc.msg)
require.Equal(t, tc.c1, c, tc.msg)
} else {
require.Error(t, err, tc.msg)
}
}
}
+116 -3
View File
@@ -7,13 +7,13 @@ import (
"time"
"github.com/pkg/errors"
"github.com/tendermint/tendermint/crypto/tmhash"
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/crypto"
cryptoenc "github.com/tendermint/tendermint/crypto/encoding"
"github.com/tendermint/tendermint/crypto/merkle"
"github.com/tendermint/tendermint/crypto/tmhash"
tmproto "github.com/tendermint/tendermint/proto/types"
)
const (
@@ -69,6 +69,118 @@ type Evidence interface {
String() string
}
func EvidenceToProto(evidence Evidence) (*tmproto.Evidence, error) {
if evidence == nil {
return nil, errors.New("nil evidence")
}
switch evi := evidence.(type) {
case *DuplicateVoteEvidence:
voteB := evi.VoteB.ToProto()
voteA := evi.VoteA.ToProto()
pk, err := cryptoenc.PubKeyToProto(evi.PubKey)
if err != nil {
return nil, err
}
tp := &tmproto.Evidence{
Sum: &tmproto.Evidence_DuplicateVoteEvidence{
DuplicateVoteEvidence: &tmproto.DuplicateVoteEvidence{
PubKey: &pk,
VoteA: voteA,
VoteB: voteB,
},
},
}
return tp, nil
case MockEvidence:
if err := evi.ValidateBasic(); err != nil {
return nil, err
}
tp := &tmproto.Evidence{
Sum: &tmproto.Evidence_MockEvidence{
MockEvidence: &tmproto.MockEvidence{
EvidenceHeight: evi.Height(),
EvidenceTime: evi.Time(),
EvidenceAddress: evi.Address(),
},
},
}
return tp, nil
case MockRandomEvidence:
if err := evi.ValidateBasic(); err != nil {
return nil, err
}
tp := &tmproto.Evidence{
Sum: &tmproto.Evidence_MockRandomEvidence{
MockRandomEvidence: &tmproto.MockRandomEvidence{
EvidenceHeight: evi.Height(),
EvidenceTime: evi.Time(),
EvidenceAddress: evi.Address(),
RandBytes: evi.randBytes,
},
},
}
return tp, nil
default:
return nil, fmt.Errorf("toproto: evidence is not recognized: %T", evi)
}
}
func EvidenceFromProto(evidence *tmproto.Evidence) (Evidence, error) {
if evidence == nil {
return nil, errors.New("nil evidence")
}
switch evi := evidence.Sum.(type) {
case *tmproto.Evidence_DuplicateVoteEvidence:
vA, err := VoteFromProto(evi.DuplicateVoteEvidence.VoteA)
if err != nil {
return nil, err
}
vB, err := VoteFromProto(evi.DuplicateVoteEvidence.VoteB)
if err != nil {
return nil, err
}
pk, err := cryptoenc.PubKeyFromProto(evi.DuplicateVoteEvidence.GetPubKey())
if err != nil {
return nil, err
}
dve := DuplicateVoteEvidence{
PubKey: pk,
VoteA: vA,
VoteB: vB,
}
return &dve, dve.ValidateBasic()
case *tmproto.Evidence_MockEvidence:
me := MockEvidence{
EvidenceHeight: evi.MockEvidence.GetEvidenceHeight(),
EvidenceAddress: evi.MockEvidence.GetEvidenceAddress(),
EvidenceTime: evi.MockEvidence.GetEvidenceTime(),
}
return me, me.ValidateBasic()
case *tmproto.Evidence_MockRandomEvidence:
mre := MockRandomEvidence{
MockEvidence: MockEvidence{
EvidenceHeight: evi.MockRandomEvidence.GetEvidenceHeight(),
EvidenceAddress: evi.MockRandomEvidence.GetEvidenceAddress(),
EvidenceTime: evi.MockRandomEvidence.GetEvidenceTime(),
},
randBytes: evi.MockRandomEvidence.RandBytes,
}
return mre, mre.ValidateBasic()
default:
return nil, errors.New("evidence is not recognized")
}
}
func RegisterEvidences(cdc *amino.Codec) {
cdc.RegisterInterface((*Evidence)(nil), nil)
cdc.RegisterConcrete(&DuplicateVoteEvidence{}, "tendermint/DuplicateVoteEvidence", nil)
@@ -221,6 +333,7 @@ func (dve *DuplicateVoteEvidence) Equal(ev Evidence) bool {
// just check their hashes
dveHash := tmhash.Sum(cdcEncode(dve))
evHash := tmhash.Sum(cdcEncode(ev))
fmt.Println(dveHash, evHash)
return bytes.Equal(dveHash, evHash)
}
+41
View File
@@ -176,3 +176,44 @@ func TestMockBadEvidenceValidateBasic(t *testing.T) {
badEvidence := NewMockEvidence(int64(1), time.Now(), 1, []byte{1})
assert.Nil(t, badEvidence.ValidateBasic())
}
func TestEvidenceProto(t *testing.T) {
// -------- Votes --------
val := NewMockPV()
blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
const chainID = "mychain"
v := makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, 1, 0x01, blockID)
v2 := makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, 2, 0x01, blockID2)
tests := []struct {
testName string
evidence Evidence
wantErr bool
wantErr2 bool
}{
{"&DuplicateVoteEvidence empty fail", &DuplicateVoteEvidence{}, true, true},
{"&DuplicateVoteEvidence nil voteB", &DuplicateVoteEvidence{VoteA: v, VoteB: nil}, true, true},
{"&DuplicateVoteEvidence nil voteA", &DuplicateVoteEvidence{VoteA: nil, VoteB: v}, true, true},
{"&DuplicateVoteEvidence success", &DuplicateVoteEvidence{VoteA: v2, VoteB: v,
PubKey: val.PrivKey.PubKey()}, false, false},
}
for _, tt := range tests {
tt := tt
t.Run(tt.testName, func(t *testing.T) {
pb, err := EvidenceToProto(tt.evidence)
if tt.wantErr {
assert.Error(t, err, tt.testName)
return
}
assert.NoError(t, err, tt.testName)
evi, err := EvidenceFromProto(pb)
if tt.wantErr2 {
assert.Error(t, err, tt.testName)
return
}
require.Equal(t, tt.evidence, evi, tt.testName)
})
}
}
+25
View File
@@ -12,6 +12,7 @@ import (
"github.com/tendermint/tendermint/libs/bits"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
tmmath "github.com/tendermint/tendermint/libs/math"
tmproto "github.com/tendermint/tendermint/proto/types"
)
var (
@@ -85,6 +86,30 @@ func (psh PartSetHeader) ValidateBasic() error {
return nil
}
// ToProto converts BloPartSetHeaderckID to protobuf
func (psh *PartSetHeader) ToProto() tmproto.PartSetHeader {
if psh == nil {
return tmproto.PartSetHeader{}
}
return tmproto.PartSetHeader{
Total: int64(psh.Total),
Hash: psh.Hash,
}
}
// FromProto sets a protobuf PartSetHeader to the given pointer
func PartSetHeaderFromProto(ppsh *tmproto.PartSetHeader) (*PartSetHeader, error) {
if ppsh == nil {
return nil, errors.New("nil PartSetHeader")
}
psh := new(PartSetHeader)
psh.Total = int(ppsh.Total)
psh.Hash = ppsh.Hash
return psh, psh.ValidateBasic()
}
//-------------------------------------
type PartSet struct {
+23
View File
@@ -136,3 +136,26 @@ func TestPartValidateBasic(t *testing.T) {
})
}
}
func TestParSetHeaderProtoBuf(t *testing.T) {
testCases := []struct {
msg string
ps1 *PartSetHeader
expPass bool
}{
{"success empty", &PartSetHeader{}, true},
{"success",
&PartSetHeader{Total: 1, Hash: []byte("hash")}, true},
}
for _, tc := range testCases {
protoBlockID := tc.ps1.ToProto()
psh, err := PartSetHeaderFromProto(&protoBlockID)
if tc.expPass {
require.Equal(t, tc.ps1, psh, tc.msg)
} else {
require.Error(t, err, tc.msg)
}
}
}
+44
View File
@@ -6,6 +6,7 @@ import (
"time"
"github.com/tendermint/tendermint/libs/bytes"
tmproto "github.com/tendermint/tendermint/proto/types"
tmtime "github.com/tendermint/tendermint/types/time"
)
@@ -95,3 +96,46 @@ func (p *Proposal) SignBytes(chainID string) []byte {
}
return bz
}
// ToProto converts Proposal to protobuf
func (p *Proposal) ToProto() *tmproto.Proposal {
if p == nil {
return nil
}
pb := new(tmproto.Proposal)
pb.BlockID = p.BlockID.ToProto()
pb.Type = tmproto.SignedMsgType(p.Type)
pb.Height = p.Height
pb.Round = int32(p.Round)
pb.PolRound = int32(p.POLRound)
pb.Timestamp = p.Timestamp
pb.Signature = p.Signature
return pb
}
// FromProto sets a protobuf Proposal to the given pointer.
// It returns an error if the proposal is invalid.
func ProposalFromProto(pp *tmproto.Proposal) (*Proposal, error) {
if pp == nil {
return nil, errors.New("nil proposal")
}
p := new(Proposal)
blockID, err := BlockIDFromProto(&pp.BlockID)
if err != nil {
return nil, err
}
p.BlockID = *blockID
p.Type = SignedMsgType(pp.Type)
p.Height = pp.Height
p.Round = int(pp.Round)
p.POLRound = int(pp.PolRound)
p.Timestamp = pp.Timestamp
p.Signature = pp.Signature
return p, p.ValidateBasic()
}
+28
View File
@@ -142,3 +142,31 @@ func TestProposalValidateBasic(t *testing.T) {
})
}
}
func TestProposalProtoBuf(t *testing.T) {
proposal := NewProposal(1, 2, 3, makeBlockID([]byte("hash"), 2, []byte("part_set_hash")))
proposal.Signature = []byte("sig")
proposal2 := NewProposal(1, 2, 3, BlockID{})
testCases := []struct {
msg string
p1 *Proposal
expPass bool
}{
{"success", proposal, true},
{"success", proposal2, false}, // blcokID cannot be empty
{"empty proposal failure validatebasic", &Proposal{}, false},
{"nil proposal", nil, false},
}
for _, tc := range testCases {
protoProposal := tc.p1.ToProto()
p, err := ProposalFromProto(protoProposal)
if tc.expPass {
require.NoError(t, err)
require.Equal(t, tc.p1, p, tc.msg)
} else {
require.Error(t, err)
}
}
}
+44
View File
@@ -2,11 +2,14 @@ package types
import (
"bytes"
"errors"
"fmt"
"strings"
"github.com/tendermint/tendermint/crypto"
ce "github.com/tendermint/tendermint/crypto/encoding"
tmrand "github.com/tendermint/tendermint/libs/rand"
tmproto "github.com/tendermint/tendermint/proto/types"
)
// Volatile state for each Validator
@@ -94,6 +97,47 @@ func (v *Validator) Bytes() []byte {
})
}
// ToProto converts Valiator to protobuf
func (v *Validator) ToProto() (*tmproto.Validator, error) {
if v == nil {
return nil, errors.New("nil validator")
}
pk, err := ce.PubKeyToProto(v.PubKey)
if err != nil {
return nil, err
}
vp := tmproto.Validator{
Address: v.Address,
PubKey: pk,
VotingPower: v.VotingPower,
ProposerPriority: v.ProposerPriority,
}
return &vp, nil
}
// FromProto sets a protobuf Validator to the given pointer.
// It returns an error if the public key is invalid.
func ValidatorFromProto(vp *tmproto.Validator) (*Validator, error) {
if vp == nil {
return nil, errors.New("nil validator")
}
pk, err := ce.PubKeyFromProto(&vp.PubKey)
if err != nil {
return nil, err
}
v := new(Validator)
v.Address = vp.GetAddress()
v.PubKey = pk
v.VotingPower = vp.GetVotingPower()
v.ProposerPriority = vp.GetProposerPriority()
return v, nil
}
//----------------------------------------
// RandValidator
+59
View File
@@ -12,6 +12,7 @@ import (
"github.com/tendermint/tendermint/crypto/merkle"
tmmath "github.com/tendermint/tendermint/libs/math"
tmproto "github.com/tendermint/tendermint/proto/types"
)
const (
@@ -902,6 +903,64 @@ func (valz ValidatorsByAddress) Swap(i, j int) {
valz[j] = it
}
// ToProto converts ValidatorSet to protobuf
func (vals *ValidatorSet) ToProto() (*tmproto.ValidatorSet, error) {
if vals == nil {
return nil, errors.New("nil validator set") // validator set should never be nil
}
vp := new(tmproto.ValidatorSet)
valsProto := make([]*tmproto.Validator, len(vals.Validators))
for i := 0; i < len(vals.Validators); i++ {
valp, err := vals.Validators[i].ToProto()
if err != nil {
return nil, err
}
valsProto[i] = valp
}
vp.Validators = valsProto
valProposer, err := vals.Proposer.ToProto()
if err != nil {
return nil, fmt.Errorf("toProto: validatorSet proposer error: %w", err)
}
vp.Proposer = valProposer
vp.TotalVotingPower = vals.totalVotingPower
return vp, nil
}
// ValidatorSetFromProto sets a protobuf ValidatorSet to the given pointer.
// It returns an error if any of the validators from the set or the proposer
// is invalid
func ValidatorSetFromProto(vp *tmproto.ValidatorSet) (*ValidatorSet, error) {
if vp == nil {
return nil, errors.New("nil validator set") // validator set should never be nil, bigger issues are at play if empty
}
vals := new(ValidatorSet)
valsProto := make([]*Validator, len(vp.Validators))
for i := 0; i < len(vp.Validators); i++ {
v, err := ValidatorFromProto(vp.Validators[i])
if err != nil {
return nil, err
}
valsProto[i] = v
}
vals.Validators = valsProto
p, err := ValidatorFromProto(vp.GetProposer())
if err != nil {
return nil, fmt.Errorf("fromProto: validatorSet proposer error: %w", err)
}
vals.Proposer = p
vals.totalVotingPower = vp.GetTotalVotingPower()
return vals, nil
}
//----------------------------------------
// for testing
+42
View File
@@ -1408,6 +1408,48 @@ func TestSafeMul(t *testing.T) {
}
}
func TestValidatorSetProtoBuf(t *testing.T) {
valset, _ := RandValidatorSet(10, 100)
valset2, _ := RandValidatorSet(10, 100)
valset2.Validators[0] = &Validator{}
valset3, _ := RandValidatorSet(10, 100)
valset3.Proposer = nil
valset4, _ := RandValidatorSet(10, 100)
valset4.Proposer = &Validator{}
testCases := []struct {
msg string
v1 *ValidatorSet
expPass1 bool
expPass2 bool
}{
{"success", valset, true, true},
{"fail valSet2, pubkey empty", valset2, false, false},
{"fail nil Proposer", valset3, false, false},
{"fail empty Proposer", valset4, false, false},
{"fail empty valSet", &ValidatorSet{}, false, false},
{"false nil", nil, false, false},
}
for _, tc := range testCases {
protoValSet, err := tc.v1.ToProto()
if tc.expPass1 {
require.NoError(t, err, tc.msg)
} else {
require.Error(t, err, tc.msg)
}
valSet, err := ValidatorSetFromProto(protoValSet)
if tc.expPass2 {
require.NoError(t, err, tc.msg)
require.EqualValues(t, tc.v1, valSet, tc.msg)
} else {
require.Error(t, err, tc.msg)
}
}
}
//---------------------
// Sort validators by priority and address
type validatorsByPriority []*Validator
+38
View File
@@ -0,0 +1,38 @@
package types
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestValidatorProtoBuf(t *testing.T) {
val, _ := RandValidator(true, 100)
testCases := []struct {
msg string
v1 *Validator
expPass1 bool
expPass2 bool
}{
{"success validator", val, true, true},
{"failure empty", &Validator{}, false, false},
{"failure nil", nil, false, false},
}
for _, tc := range testCases {
protoVal, err := tc.v1.ToProto()
if tc.expPass1 {
require.NoError(t, err, tc.msg)
} else {
require.Error(t, err, tc.msg)
}
val, err := ValidatorFromProto(protoVal)
if tc.expPass2 {
require.NoError(t, err, tc.msg)
require.Equal(t, tc.v1, val, tc.msg)
} else {
require.Error(t, err, tc.msg)
}
}
}
+45
View File
@@ -8,6 +8,7 @@ import (
"github.com/tendermint/tendermint/crypto"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
tmproto "github.com/tendermint/tendermint/proto/types"
)
const (
@@ -171,3 +172,47 @@ func (vote *Vote) ValidateBasic() error {
}
return nil
}
// ToProto converts the handwritten type to proto generated type
// return type, nil if everything converts safely, otherwise nil, error
func (vote *Vote) ToProto() *tmproto.Vote {
if vote == nil {
return nil
}
return &tmproto.Vote{
Type: tmproto.SignedMsgType(vote.Type),
Height: vote.Height,
Round: int64(vote.Round),
BlockID: vote.BlockID.ToProto(),
Timestamp: vote.Timestamp,
ValidatorAddress: vote.ValidatorAddress,
ValidatorIndex: int64(vote.ValidatorIndex),
Signature: vote.Signature,
}
}
//FromProto converts a proto generetad type to a handwritten type
// return type, nil if everything converts safely, otherwise nil, error
func VoteFromProto(pv *tmproto.Vote) (*Vote, error) {
if pv == nil {
return nil, errors.New("nil vote")
}
blockID, err := BlockIDFromProto(&pv.BlockID)
if err != nil {
return nil, err
}
vote := new(Vote)
vote.Type = SignedMsgType(pv.Type)
vote.Height = pv.Height
vote.Round = int(pv.Round)
vote.BlockID = *blockID
vote.Timestamp = pv.Timestamp
vote.ValidatorAddress = pv.ValidatorAddress
vote.ValidatorIndex = int(pv.ValidatorIndex)
vote.Signature = pv.Signature
return vote, vote.ValidateBasic()
}
+28
View File
@@ -286,3 +286,31 @@ func TestVoteValidateBasic(t *testing.T) {
})
}
}
func TestVoteProtobuf(t *testing.T) {
privVal := NewMockPV()
vote := examplePrecommit()
err := privVal.SignVote("test_chain_id", vote)
require.NoError(t, err)
testCases := []struct {
msg string
v1 *Vote
expPass bool
}{
{"success", vote, true},
{"fail vote validate basic", &Vote{}, false},
{"failure nil", nil, false},
}
for _, tc := range testCases {
protoProposal := tc.v1.ToProto()
v, err := VoteFromProto(protoProposal)
if tc.expPass {
require.NoError(t, err)
require.Equal(t, tc.v1, v, tc.msg)
} else {
require.Error(t, err)
}
}
}