mirror of
https://github.com/tendermint/tendermint.git
synced 2026-09-12 02:56:21 +00:00
these proto files are meant to help unblock ibc in their quest of migrating the ibc module to proto.
This commit is contained in:
+229
-10
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user