proto: leftover amino (#4986)

This commit is contained in:
Marko
2020-06-15 11:14:36 +02:00
committed by GitHub
parent a37480c396
commit 74cae49c3b
41 changed files with 2173 additions and 684 deletions

View File

@@ -9,6 +9,7 @@ import (
"time"
"github.com/gogo/protobuf/proto"
gogotypes "github.com/gogo/protobuf/types"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/merkle"
@@ -21,10 +22,10 @@ import (
)
const (
// MaxHeaderBytes is a maximum header size (including amino overhead).
MaxHeaderBytes int64 = 628
// MaxHeaderBytes is a maximum header size.
MaxHeaderBytes int64 = 626
// MaxAminoOverheadForBlock - maximum amino overhead to encode a block (up to
// MaxOverheadForBlock - maximum overhead to encode a block (up to
// MaxBlockSizeBytes in size) not including it's parts except Data.
// This means it also excludes the overhead for individual transactions.
//
@@ -32,7 +33,7 @@ const (
// 2 fields (2 embedded): 2 bytes
// Uvarint length of Data.Txs: 4 bytes
// Data.Txs field: 1 byte
MaxAminoOverheadForBlock int64 = 11
MaxOverheadForBlock int64 = 11
)
// Block defines the atomic unit of a Tendermint blockchain.
@@ -167,11 +168,12 @@ func (b *Block) HashesTo(hash []byte) bool {
// Size returns size of the block in bytes.
func (b *Block) Size() int {
bz, err := cdc.MarshalBinaryBare(b)
pbb, err := b.ToProto()
if err != nil {
return 0
}
return len(bz)
return pbb.Size()
}
// String returns a string representation of the block
@@ -257,28 +259,6 @@ func BlockFromProto(bp *tmproto.Block) (*Block, error) {
return b, b.ValidateBasic()
}
//-----------------------------------------------------------
// These methods are for Protobuf Compatibility
// Marshal returns the amino encoding.
func (b *Block) Marshal() ([]byte, error) {
return cdc.MarshalBinaryBare(b)
}
// MarshalTo calls Marshal and copies to the given buffer.
func (b *Block) MarshalTo(data []byte) (int, error) {
bs, err := b.Marshal()
if err != nil {
return -1, err
}
return copy(data, bs), nil
}
// Unmarshal deserializes from amino encoded form.
func (b *Block) Unmarshal(bs []byte) error {
return cdc.UnmarshalBinaryBare(bs, b)
}
//-----------------------------------------------------------------------------
// MaxDataBytes returns the maximum size of block's data.
@@ -286,7 +266,7 @@ func (b *Block) Unmarshal(bs []byte) error {
// XXX: Panics on negative result.
func MaxDataBytes(maxBytes int64, valsCount, evidenceCount int) int64 {
maxDataBytes := maxBytes -
MaxAminoOverheadForBlock -
MaxOverheadForBlock -
MaxHeaderBytes -
int64(valsCount)*MaxVoteBytes -
int64(evidenceCount)*MaxEvidenceBytes
@@ -311,7 +291,7 @@ func MaxDataBytes(maxBytes int64, valsCount, evidenceCount int) int64 {
func MaxDataBytesUnknownEvidence(maxBytes int64, valsCount int, maxNumEvidence uint32) int64 {
maxEvidenceBytes := int64(maxNumEvidence) * MaxEvidenceBytes
maxDataBytes := maxBytes -
MaxAminoOverheadForBlock -
MaxOverheadForBlock -
MaxHeaderBytes -
int64(valsCount)*MaxVoteBytes -
maxEvidenceBytes
@@ -449,12 +429,27 @@ func (h *Header) Hash() tmbytes.HexBytes {
if h == nil || len(h.ValidatorsHash) == 0 {
return nil
}
hbz, err := h.Version.Marshal()
if err != nil {
return nil
}
pbt, err := gogotypes.StdTimeMarshal(h.Time)
if err != nil {
return nil
}
pbbi := h.LastBlockID.ToProto()
bzbi, err := pbbi.Marshal()
if err != nil {
return nil
}
return merkle.HashFromByteSlices([][]byte{
cdcEncode(h.Version),
hbz,
cdcEncode(h.ChainID),
cdcEncode(h.Height),
cdcEncode(h.Time),
cdcEncode(h.LastBlockID),
pbt,
bzbi,
cdcEncode(h.LastCommitHash),
cdcEncode(h.DataHash),
cdcEncode(h.ValidatorsHash),
@@ -866,7 +861,13 @@ func (commit *Commit) Hash() tmbytes.HexBytes {
if commit.hash == nil {
bs := make([][]byte, len(commit.Signatures))
for i, commitSig := range commit.Signatures {
bs[i] = cdcEncode(commitSig)
pbcs := commitSig.ToProto()
bz, err := pbcs.Marshal()
if err != nil {
panic(err)
}
bs[i] = bz
}
commit.hash = merkle.HashFromByteSlices(bs)
}
@@ -1248,10 +1249,12 @@ func (blockID BlockID) Equals(other BlockID) bool {
// Key returns a machine-readable string representation of the BlockID
func (blockID BlockID) Key() string {
bz, err := cdc.MarshalBinaryBare(blockID.PartsHeader)
pbph := blockID.PartsHeader.ToProto()
bz, err := pbph.Marshal()
if err != nil {
panic(err)
}
return string(blockID.Hash) + string(bz)
}

View File

@@ -65,34 +65,6 @@ func BlockMetaFromProto(pb *tmproto.BlockMeta) (*BlockMeta, error) {
return bm, bm.ValidateBasic()
}
//-----------------------------------------------------------
// These methods are for Protobuf Compatibility
// Size returns the size of the amino encoding, in bytes.
func (bm *BlockMeta) Size() int {
bs, _ := bm.Marshal()
return len(bs)
}
// Marshal returns the amino encoding.
func (bm *BlockMeta) Marshal() ([]byte, error) {
return cdc.MarshalBinaryBare(bm)
}
// MarshalTo calls Marshal and copies to the given buffer.
func (bm *BlockMeta) MarshalTo(data []byte) (int, error) {
bs, err := bm.Marshal()
if err != nil {
return -1, err
}
return copy(data, bs), nil
}
// Unmarshal deserializes from amino encoded form.
func (bm *BlockMeta) Unmarshal(bs []byte) error {
return cdc.UnmarshalBinaryBare(bs, bm)
}
// ValidateBasic performs basic validation.
func (bm *BlockMeta) ValidateBasic() error {
if err := bm.BlockID.ValidateBasic(); err != nil {

View File

@@ -11,6 +11,7 @@ import (
"testing"
"time"
gogotypes "github.com/gogo/protobuf/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -26,8 +27,6 @@ import (
)
func TestMain(m *testing.M) {
RegisterMockEvidences(cdc)
code := m.Run()
os.Exit(code)
}
@@ -270,7 +269,7 @@ func TestHeaderHash(t *testing.T) {
LastResultsHash: tmhash.Sum([]byte("last_results_hash")),
EvidenceHash: tmhash.Sum([]byte("evidence_hash")),
ProposerAddress: crypto.AddressHash([]byte("proposer_address")),
}, hexBytesFromString("ABDC78921B18A47EE6BEF5E31637BADB0F3E587E3C0F4DB2D1E93E9FF0533862")},
}, hexBytesFromString("F740121F553B5418C3EFBD343C2DBFE9E007BB67B0D020A0741374BAB65242A4")},
{"nil header yields nil", nil, nil},
{"nil ValidatorsHash yields nil", &Header{
Version: version.Consensus{Block: 1, App: 2},
@@ -298,12 +297,33 @@ func TestHeaderHash(t *testing.T) {
// fields in the test struct are non-zero.
if tc.header != nil && tc.expectHash != nil {
byteSlices := [][]byte{}
s := reflect.ValueOf(*tc.header)
for i := 0; i < s.NumField(); i++ {
f := s.Field(i)
assert.False(t, f.IsZero(), "Found zero-valued field %v",
s.Type().Field(i).Name)
byteSlices = append(byteSlices, cdcEncode(f.Interface()))
switch f := f.Interface().(type) {
case int64, bytes.HexBytes, string:
byteSlices = append(byteSlices, cdcEncode(f))
case time.Time:
bz, err := gogotypes.StdTimeMarshal(f)
require.NoError(t, err)
byteSlices = append(byteSlices, bz)
case version.Consensus:
bz, err := f.Marshal()
require.NoError(t, err)
byteSlices = append(byteSlices, bz)
case BlockID:
pbbi := f.ToProto()
bz, err := pbbi.Marshal()
require.NoError(t, err)
byteSlices = append(byteSlices, bz)
default:
t.Errorf("unknown type %T", f)
}
}
assert.Equal(t,
bytes.HexBytes(merkle.HashFromByteSlices(byteSlices)), tc.header.Hash())
@@ -343,7 +363,7 @@ func TestMaxHeaderBytes(t *testing.T) {
ProposerAddress: crypto.AddressHash([]byte("proposer_address")),
}
bz, err := cdc.MarshalBinaryLengthPrefixed(h)
bz, err := h.ToProto().Marshal()
require.NoError(t, err)
assert.EqualValues(t, MaxHeaderBytes, int64(len(bz)))
@@ -378,9 +398,9 @@ func TestBlockMaxDataBytes(t *testing.T) {
}{
0: {-10, 1, 0, true, 0},
1: {10, 1, 0, true, 0},
2: {846, 1, 0, true, 0},
3: {848, 1, 0, false, 0},
4: {849, 1, 0, false, 1},
2: {844, 1, 0, true, 0},
3: {846, 1, 0, false, 0},
4: {847, 1, 0, false, 1},
}
for i, tc := range testCases {
@@ -408,10 +428,10 @@ func TestBlockMaxDataBytesUnknownEvidence(t *testing.T) {
}{
0: {-10, 0, 1, true, 0},
1: {10, 0, 1, true, 0},
2: {847, 0, 1, true, 0},
3: {848, 0, 1, false, 0},
4: {1292, 1, 1, false, 0},
5: {1293, 1, 1, false, 1},
2: {845, 0, 1, true, 0},
3: {846, 0, 1, false, 0},
4: {1290, 1, 1, false, 0},
5: {1291, 1, 1, false, 1},
}
for i, tc := range testCases {
@@ -445,9 +465,12 @@ func TestCommitToVoteSet(t *testing.T) {
vote2 := voteSet2.GetByIndex(i)
vote3 := commit.GetVote(i)
vote1bz := cdc.MustMarshalBinaryBare(vote1)
vote2bz := cdc.MustMarshalBinaryBare(vote2)
vote3bz := cdc.MustMarshalBinaryBare(vote3)
vote1bz, err := vote1.ToProto().Marshal()
require.NoError(t, err)
vote2bz, err := vote2.ToProto().Marshal()
require.NoError(t, err)
vote3bz, err := vote3.ToProto().Marshal()
require.NoError(t, err)
assert.Equal(t, vote1bz, vote2bz)
assert.Equal(t, vote1bz, vote3bz)
}

View File

@@ -1,28 +0,0 @@
package types
import (
amino "github.com/tendermint/go-amino"
cryptoamino "github.com/tendermint/tendermint/crypto/encoding/amino"
)
var cdc = amino.NewCodec()
func init() {
RegisterBlockAmino(cdc)
}
func RegisterBlockAmino(cdc *amino.Codec) {
cryptoamino.RegisterAmino(cdc)
RegisterEvidences(cdc)
}
// GetCodec returns a codec used by the package. For testing purposes only.
func GetCodec() *amino.Codec {
return cdc
}
// For testing purposes only
func RegisterMockEvidencesGlobal() {
RegisterMockEvidences(cdc)
}

View File

@@ -1,10 +1,47 @@
package types
import (
gogotypes "github.com/gogo/protobuf/types"
"github.com/tendermint/tendermint/libs/bytes"
)
// cdcEncode returns nil if the input is nil, otherwise returns
// cdc.MustMarshalBinaryBare(item)
// proto.Marshal(<type>Value{Value: item})
func cdcEncode(item interface{}) []byte {
if item != nil && !isTypedNil(item) && !isEmpty(item) {
return cdc.MustMarshalBinaryBare(item)
switch item := item.(type) {
case string:
i := gogotypes.StringValue{
Value: item,
}
bz, err := i.Marshal()
if err != nil {
return nil
}
return bz
case int64:
i := gogotypes.Int64Value{
Value: item,
}
bz, err := i.Marshal()
if err != nil {
return nil
}
return bz
case bytes.HexBytes:
i := gogotypes.BytesValue{
Value: item,
}
bz, err := i.Marshal()
if err != nil {
return nil
}
return bz
default:
return nil
}
}
return nil
}

View File

@@ -3,8 +3,6 @@ package types
import (
"fmt"
amino "github.com/tendermint/go-amino"
abci "github.com/tendermint/tendermint/abci/types"
tmjson "github.com/tendermint/tendermint/libs/json"
tmpubsub "github.com/tendermint/tendermint/libs/pubsub"
@@ -48,19 +46,6 @@ type TMEventData interface {
// empty interface
}
func RegisterEventDatas(cdc *amino.Codec) {
cdc.RegisterInterface((*TMEventData)(nil), nil)
cdc.RegisterConcrete(EventDataNewBlock{}, "tendermint/event/NewBlock", nil)
cdc.RegisterConcrete(EventDataNewBlockHeader{}, "tendermint/event/NewBlockHeader", nil)
cdc.RegisterConcrete(EventDataTx{}, "tendermint/event/Tx", nil)
cdc.RegisterConcrete(EventDataRoundState{}, "tendermint/event/RoundState", nil)
cdc.RegisterConcrete(EventDataNewRound{}, "tendermint/event/NewRound", nil)
cdc.RegisterConcrete(EventDataCompleteProposal{}, "tendermint/event/CompleteProposal", nil)
cdc.RegisterConcrete(EventDataVote{}, "tendermint/event/Vote", nil)
cdc.RegisterConcrete(EventDataValidatorSetUpdates{}, "tendermint/event/ValidatorSetUpdates", nil)
cdc.RegisterConcrete(EventDataString(""), "tendermint/event/ProposalString", nil)
}
func init() {
tmjson.RegisterType(EventDataNewBlock{}, "tendermint/event/NewBlock")
tmjson.RegisterType(EventDataNewBlockHeader{}, "tendermint/event/NewBlockHeader")

View File

@@ -7,8 +7,6 @@ import (
"strings"
"time"
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/crypto"
cryptoenc "github.com/tendermint/tendermint/crypto/encoding"
"github.com/tendermint/tendermint/crypto/merkle"
@@ -91,99 +89,89 @@ func EvidenceToProto(evidence Evidence) (*tmproto.Evidence, error) {
switch evi := evidence.(type) {
case *DuplicateVoteEvidence:
voteB := evi.VoteB.ToProto()
voteA := evi.VoteA.ToProto()
pbevi := evi.ToProto()
tp := &tmproto.Evidence{
Sum: &tmproto.Evidence_DuplicateVoteEvidence{
DuplicateVoteEvidence: &tmproto.DuplicateVoteEvidence{
VoteA: voteA,
VoteB: voteB,
},
DuplicateVoteEvidence: &pbevi,
},
}
return tp, nil
case ConflictingHeadersEvidence:
pbh1 := evi.H1.ToProto()
pbh2 := evi.H2.ToProto()
pbevi := evi.ToProto()
tp := &tmproto.Evidence{
Sum: &tmproto.Evidence_ConflictingHeadersEvidence{
ConflictingHeadersEvidence: &tmproto.ConflictingHeadersEvidence{
H1: pbh1,
H2: pbh2,
},
ConflictingHeadersEvidence: &pbevi,
},
}
return tp, nil
case *ConflictingHeadersEvidence:
pbh1 := evi.H1.ToProto()
pbh2 := evi.H2.ToProto()
pbevi := evi.ToProto()
tp := &tmproto.Evidence{
Sum: &tmproto.Evidence_ConflictingHeadersEvidence{
ConflictingHeadersEvidence: &tmproto.ConflictingHeadersEvidence{
H1: pbh1,
H2: pbh2,
},
ConflictingHeadersEvidence: &pbevi,
},
}
return tp, nil
case *LunaticValidatorEvidence:
h := evi.Header.ToProto()
v := evi.Vote.ToProto()
pbevi := evi.ToProto()
tp := &tmproto.Evidence{
Sum: &tmproto.Evidence_LunaticValidatorEvidence{
LunaticValidatorEvidence: &tmproto.LunaticValidatorEvidence{
Header: h,
Vote: v,
InvalidHeaderField: evi.InvalidHeaderField,
},
LunaticValidatorEvidence: &pbevi,
},
}
return tp, nil
case LunaticValidatorEvidence:
h := evi.Header.ToProto()
v := evi.Vote.ToProto()
pbevi := evi.ToProto()
tp := &tmproto.Evidence{
Sum: &tmproto.Evidence_LunaticValidatorEvidence{
LunaticValidatorEvidence: &tmproto.LunaticValidatorEvidence{
Header: h,
Vote: v,
InvalidHeaderField: evi.InvalidHeaderField,
},
LunaticValidatorEvidence: &pbevi,
},
}
return tp, nil
case *PhantomValidatorEvidence:
pbevi := evi.ToProto()
tp := &tmproto.Evidence{
Sum: &tmproto.Evidence_PhantomValidatorEvidence{
PhantomValidatorEvidence: &pbevi,
},
}
return tp, nil
case PhantomValidatorEvidence:
pbevi := evi.ToProto()
tp := &tmproto.Evidence{
Sum: &tmproto.Evidence_PhantomValidatorEvidence{
PhantomValidatorEvidence: &pbevi,
},
}
return tp, nil
case *PotentialAmnesiaEvidence:
voteB := evi.VoteB.ToProto()
voteA := evi.VoteA.ToProto()
pbevi := evi.ToProto()
tp := &tmproto.Evidence{
Sum: &tmproto.Evidence_PotentialAmnesiaEvidence{
PotentialAmnesiaEvidence: &tmproto.PotentialAmnesiaEvidence{
VoteA: voteA,
VoteB: voteB,
HeightStamp: evi.HeightStamp,
},
PotentialAmnesiaEvidence: &pbevi,
},
}
return tp, nil
case PotentialAmnesiaEvidence:
voteB := evi.VoteB.ToProto()
voteA := evi.VoteA.ToProto()
pbevi := evi.ToProto()
tp := &tmproto.Evidence{
Sum: &tmproto.Evidence_PotentialAmnesiaEvidence{
PotentialAmnesiaEvidence: &tmproto.PotentialAmnesiaEvidence{
VoteA: voteA,
VoteB: voteB,
HeightStamp: evi.HeightStamp,
},
PotentialAmnesiaEvidence: &pbevi,
},
}
return tp, nil
@@ -238,78 +226,17 @@ func EvidenceFromProto(evidence *tmproto.Evidence) (Evidence, error) {
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
}
dve := DuplicateVoteEvidence{
VoteA: vA,
VoteB: vB,
}
return &dve, dve.ValidateBasic()
return DuplicateVoteEvidenceFromProto(evi.DuplicateVoteEvidence)
case *tmproto.Evidence_ConflictingHeadersEvidence:
h1, err := SignedHeaderFromProto(evi.ConflictingHeadersEvidence.H1)
if err != nil {
return nil, fmt.Errorf("from proto err: %w", err)
}
h2, err := SignedHeaderFromProto(evi.ConflictingHeadersEvidence.H2)
if err != nil {
return nil, fmt.Errorf("from proto err: %w", err)
}
tp := ConflictingHeadersEvidence{
H1: h1,
H2: h2,
}
return tp, tp.ValidateBasic()
return ConflictingHeadersEvidenceFromProto(evi.ConflictingHeadersEvidence)
case *tmproto.Evidence_LunaticValidatorEvidence:
h, err := HeaderFromProto(evi.LunaticValidatorEvidence.GetHeader())
if err != nil {
return nil, err
}
v, err := VoteFromProto(evi.LunaticValidatorEvidence.GetVote())
if err != nil {
return nil, err
}
tp := LunaticValidatorEvidence{
Header: &h,
Vote: v,
InvalidHeaderField: evi.LunaticValidatorEvidence.InvalidHeaderField,
}
return &tp, tp.ValidateBasic()
return LunaticValidatorEvidenceFromProto(evi.LunaticValidatorEvidence)
case *tmproto.Evidence_PotentialAmnesiaEvidence:
return PotentialAmnesiaEvidenceFromProto(evi.PotentialAmnesiaEvidence)
case *tmproto.Evidence_AmnesiaEvidence:
pae, err := PotentialAmnesiaEvidenceFromProto(evi.AmnesiaEvidence.PotentialAmnesiaEvidence)
if err != nil {
return nil, err
}
polc, err := ProofOfLockChangeFromProto(evi.AmnesiaEvidence.Polc)
if err != nil {
return nil, err
}
tp := AmnesiaEvidence{
PotentialAmnesiaEvidence: *pae,
Polc: *polc,
}
return tp, tp.ValidateBasic()
return AmensiaEvidenceFromProto(evi.AmnesiaEvidence)
case *tmproto.Evidence_PhantomValidatorEvidence:
return PhantomValidatorEvidenceFromProto(evi.PhantomValidatorEvidence)
case *tmproto.Evidence_MockEvidence:
me := MockEvidence{
EvidenceHeight: evi.MockEvidence.GetEvidenceHeight(),
@@ -332,16 +259,6 @@ func EvidenceFromProto(evidence *tmproto.Evidence) (Evidence, error) {
}
}
func RegisterEvidences(cdc *amino.Codec) {
cdc.RegisterInterface((*Evidence)(nil), nil)
cdc.RegisterConcrete(&DuplicateVoteEvidence{}, "tendermint/DuplicateVoteEvidence", nil)
cdc.RegisterConcrete(&ConflictingHeadersEvidence{}, "tendermint/ConflictingHeadersEvidence", nil)
cdc.RegisterConcrete(&PhantomValidatorEvidence{}, "tendermint/PhantomValidatorEvidence", nil)
cdc.RegisterConcrete(&LunaticValidatorEvidence{}, "tendermint/LunaticValidatorEvidence", nil)
cdc.RegisterConcrete(&PotentialAmnesiaEvidence{}, "tendermint/PotentialAmnesiaEvidence", nil)
cdc.RegisterConcrete(&AmnesiaEvidence{}, "tendermint/AmnesiaEvidence", nil)
}
func init() {
tmjson.RegisterType(&DuplicateVoteEvidence{}, "tendermint/DuplicateVoteEvidence")
tmjson.RegisterType(&ConflictingHeadersEvidence{}, "tendermint/ConflictingHeadersEvidence")
@@ -351,11 +268,6 @@ func init() {
tmjson.RegisterType(&AmnesiaEvidence{}, "tendermint/AmnesiaEvidence")
}
func RegisterMockEvidences(cdc *amino.Codec) {
cdc.RegisterConcrete(MockEvidence{}, "tendermint/MockEvidence", nil)
cdc.RegisterConcrete(MockRandomEvidence{}, "tendermint/MockRandomEvidence", nil)
}
//-------------------------------------------
// DuplicateVoteEvidence contains evidence a validator signed two conflicting
@@ -410,12 +322,24 @@ func (dve *DuplicateVoteEvidence) Address() []byte {
// Hash returns the hash of the evidence.
func (dve *DuplicateVoteEvidence) Bytes() []byte {
return cdcEncode(dve)
pbe := dve.ToProto()
bz, err := pbe.Marshal()
if err != nil {
panic(err)
}
return bz
}
// Hash returns the hash of the evidence.
func (dve *DuplicateVoteEvidence) Hash() []byte {
return tmhash.Sum(cdcEncode(dve))
pbe := dve.ToProto()
bz, err := pbe.Marshal()
if err != nil {
panic(err)
}
return tmhash.Sum(bz)
}
// Verify returns an error if the two votes aren't conflicting.
@@ -481,11 +405,24 @@ func (dve *DuplicateVoteEvidence) Equal(ev Evidence) bool {
if _, ok := ev.(*DuplicateVoteEvidence); !ok {
return false
}
pbdev := dve.ToProto()
bz, err := pbdev.Marshal()
if err != nil {
panic(err)
}
var evbz []byte
if ev, ok := ev.(*DuplicateVoteEvidence); ok {
evpb := ev.ToProto()
evbz, err = evpb.Marshal()
if err != nil {
panic(err)
}
}
// just check their hashes
dveHash := tmhash.Sum(cdcEncode(dve))
evHash := tmhash.Sum(cdcEncode(ev))
fmt.Println(dveHash, evHash)
dveHash := tmhash.Sum(bz)
evHash := tmhash.Sum(evbz)
return bytes.Equal(dveHash, evHash)
}
@@ -507,6 +444,39 @@ func (dve *DuplicateVoteEvidence) ValidateBasic() error {
return nil
}
func (dve DuplicateVoteEvidence) ToProto() tmproto.DuplicateVoteEvidence {
voteB := dve.VoteB.ToProto()
voteA := dve.VoteA.ToProto()
tp := tmproto.DuplicateVoteEvidence{
VoteA: voteA,
VoteB: voteB,
}
return tp
}
func DuplicateVoteEvidenceFromProto(pb *tmproto.DuplicateVoteEvidence) (*DuplicateVoteEvidence, error) {
if pb == nil {
return nil, errors.New("nil duplicate vote evidence")
}
vA, err := VoteFromProto(pb.VoteA)
if err != nil {
return nil, err
}
vB, err := VoteFromProto(pb.VoteB)
if err != nil {
return nil, err
}
dve := new(DuplicateVoteEvidence)
dve.VoteA = vA
dve.VoteB = vB
return dve, dve.ValidateBasic()
}
//-------------------------------------------
// EvidenceList is a list of Evidence. Evidences is not a word.
@@ -715,7 +685,14 @@ func (ev ConflictingHeadersEvidence) Address() []byte {
}
func (ev ConflictingHeadersEvidence) Bytes() []byte {
return cdcEncode(ev)
pbe := ev.ToProto()
bz, err := pbe.Marshal()
if err != nil {
panic(err)
}
return bz
}
func (ev ConflictingHeadersEvidence) Hash() []byte {
@@ -811,6 +788,38 @@ func (ev ConflictingHeadersEvidence) String() string {
ev.H2.Height, ev.H2.Hash())
}
func (ev ConflictingHeadersEvidence) ToProto() tmproto.ConflictingHeadersEvidence {
pbh1 := ev.H1.ToProto()
pbh2 := ev.H2.ToProto()
tp := tmproto.ConflictingHeadersEvidence{
H1: pbh1,
H2: pbh2,
}
return tp
}
func ConflictingHeadersEvidenceFromProto(pb *tmproto.ConflictingHeadersEvidence) (ConflictingHeadersEvidence, error) {
if pb == nil {
return ConflictingHeadersEvidence{}, errors.New("nil ConflictingHeadersEvidence")
}
h1, err := SignedHeaderFromProto(pb.H1)
if err != nil {
return ConflictingHeadersEvidence{}, fmt.Errorf("from proto err: %w", err)
}
h2, err := SignedHeaderFromProto(pb.H2)
if err != nil {
return ConflictingHeadersEvidence{}, fmt.Errorf("from proto err: %w", err)
}
tp := ConflictingHeadersEvidence{
H1: h1,
H2: h2,
}
return tp, tp.ValidateBasic()
}
//-------------------------------------------
type PhantomValidatorEvidence struct {
@@ -833,11 +842,24 @@ func (e PhantomValidatorEvidence) Address() []byte {
}
func (e PhantomValidatorEvidence) Hash() []byte {
return tmhash.Sum(cdcEncode(e))
pbe := e.ToProto()
bz, err := pbe.Marshal()
if err != nil {
panic(err)
}
return tmhash.Sum(bz)
}
func (e PhantomValidatorEvidence) Bytes() []byte {
return cdcEncode(e)
pbe := e.ToProto()
bz, err := pbe.Marshal()
if err != nil {
panic(err)
}
return bz
}
func (e PhantomValidatorEvidence) Verify(chainID string, pubKey crypto.PubKey) error {
@@ -889,6 +911,35 @@ func (e PhantomValidatorEvidence) String() string {
e.Vote.ValidatorAddress, e.Vote.Height)
}
func (e PhantomValidatorEvidence) ToProto() tmproto.PhantomValidatorEvidence {
vpb := e.Vote.ToProto()
tp := tmproto.PhantomValidatorEvidence{
Vote: vpb,
LastHeightValidatorWasInSet: e.LastHeightValidatorWasInSet,
}
return tp
}
func PhantomValidatorEvidenceFromProto(pb *tmproto.PhantomValidatorEvidence) (PhantomValidatorEvidence, error) {
if pb == nil {
return PhantomValidatorEvidence{}, errors.New("nil PhantomValidatorEvidence")
}
vpb, err := VoteFromProto(pb.Vote)
if err != nil {
return PhantomValidatorEvidence{}, err
}
tp := PhantomValidatorEvidence{
Vote: vpb,
LastHeightValidatorWasInSet: pb.LastHeightValidatorWasInSet,
}
return tp, tp.ValidateBasic()
}
//-------------------------------------------
type LunaticValidatorEvidence struct {
@@ -919,7 +970,14 @@ func (e LunaticValidatorEvidence) Hash() []byte {
}
func (e LunaticValidatorEvidence) Bytes() []byte {
return cdcEncode(e)
pbe := e.ToProto()
bz, err := pbe.Marshal()
if err != nil {
panic(err)
}
return bz
}
func (e LunaticValidatorEvidence) Verify(chainID string, pubKey crypto.PubKey) error {
@@ -1030,6 +1088,43 @@ func (e LunaticValidatorEvidence) VerifyHeader(committedHeader *Header) error {
return nil
}
func (e LunaticValidatorEvidence) ToProto() tmproto.LunaticValidatorEvidence {
h := e.Header.ToProto()
v := e.Vote.ToProto()
tp := tmproto.LunaticValidatorEvidence{
Header: h,
Vote: v,
InvalidHeaderField: e.InvalidHeaderField,
}
return tp
}
func LunaticValidatorEvidenceFromProto(pb *tmproto.LunaticValidatorEvidence) (*LunaticValidatorEvidence, error) {
if pb == nil {
return nil, errors.New("nil LunaticValidatorEvidence")
}
h, err := HeaderFromProto(pb.GetHeader())
if err != nil {
return nil, err
}
v, err := VoteFromProto(pb.GetVote())
if err != nil {
return nil, err
}
tp := LunaticValidatorEvidence{
Header: &h,
Vote: v,
InvalidHeaderField: pb.InvalidHeaderField,
}
return &tp, tp.ValidateBasic()
}
//-------------------------------------------
// PotentialAmnesiaEvidence is constructed when a validator votes on two different blocks at different rounds
@@ -1059,11 +1154,25 @@ func (e PotentialAmnesiaEvidence) Address() []byte {
}
func (e PotentialAmnesiaEvidence) Hash() []byte {
return tmhash.Sum(cdcEncode(e))
pbe := e.ToProto()
bz, err := pbe.Marshal()
if err != nil {
panic(err)
}
return tmhash.Sum(bz)
}
func (e PotentialAmnesiaEvidence) Bytes() []byte {
return cdcEncode(e)
pbe := e.ToProto()
bz, err := pbe.Marshal()
if err != nil {
panic(err)
}
return bz
}
func (e PotentialAmnesiaEvidence) Verify(chainID string, pubKey crypto.PubKey) error {
@@ -1173,6 +1282,21 @@ func (e PotentialAmnesiaEvidence) Primed(trialPeriod, currentHeight int64) bool
return false
}
func (e PotentialAmnesiaEvidence) ToProto() tmproto.PotentialAmnesiaEvidence {
voteB := e.VoteB.ToProto()
voteA := e.VoteA.ToProto()
tp := tmproto.PotentialAmnesiaEvidence{
VoteA: voteA,
VoteB: voteB,
HeightStamp: e.HeightStamp,
}
return tp
}
// ------------------
// ProofOfLockChange (POLC) proves that a node followed the consensus protocol and voted for a precommit in two
// different rounds because the node received a majority of votes for a different block in the latter round. In cases of
// amnesia evidence, a suspected node will need ProofOfLockChange to prove that the node did not break protocol.
@@ -1522,15 +1646,7 @@ func PotentialAmnesiaEvidenceFromProto(pb *tmproto.PotentialAmnesiaEvidence) (*P
}
func AmnesiaEvidenceToProto(evi AmnesiaEvidence) (*tmproto.Evidence, error) {
ev, err := EvidenceToProto(evi.PotentialAmnesiaEvidence)
if err != nil {
return nil, err
}
paepb := ev.GetPotentialAmnesiaEvidence()
if paepb == nil {
return nil, errors.New("provided evidence is not potential amnesia evidence")
}
paepb := evi.PotentialAmnesiaEvidence.ToProto()
polc, err := evi.Polc.ToProto()
if err != nil {
@@ -1540,14 +1656,35 @@ func AmnesiaEvidenceToProto(evi AmnesiaEvidence) (*tmproto.Evidence, error) {
tp := &tmproto.Evidence{
Sum: &tmproto.Evidence_AmnesiaEvidence{
AmnesiaEvidence: &tmproto.AmnesiaEvidence{
PotentialAmnesiaEvidence: paepb,
PotentialAmnesiaEvidence: &paepb,
Polc: polc,
},
},
}
return tp, nil
}
func AmensiaEvidenceFromProto(pb *tmproto.AmnesiaEvidence) (AmnesiaEvidence, error) {
if pb == nil {
return AmnesiaEvidence{}, errors.New("nil duplicate vote evidence")
}
pae, err := PotentialAmnesiaEvidenceFromProto(pb.PotentialAmnesiaEvidence)
if err != nil {
return AmnesiaEvidence{}, err
}
polc, err := ProofOfLockChangeFromProto(pb.Polc)
if err != nil {
return AmnesiaEvidence{}, err
}
tp := AmnesiaEvidence{
PotentialAmnesiaEvidence: *pae,
Polc: *polc,
}
return tp, tp.ValidateBasic()
}
//-----------------------------------------------------------------

View File

@@ -135,7 +135,9 @@ func TestMaxEvidenceBytes(t *testing.T) {
}
for _, tt := range testCases {
bz, err := cdc.MarshalBinaryLengthPrefixed(tt.evidence)
pb, err := EvidenceToProto(tt.evidence)
require.NoError(t, err, tt.testName)
bz, err := pb.Marshal()
require.NoError(t, err, tt.testName)
assert.LessOrEqual(t, int64(len(bz)), MaxEvidenceBytes, tt.testName)
@@ -664,6 +666,11 @@ func TestEvidenceProto(t *testing.T) {
{"&PotentialAmnesiaEvidence nil VoteB", &PotentialAmnesiaEvidence{VoteA: v, VoteB: nil}, false, true},
{"&PotentialAmnesiaEvidence nil VoteA", &PotentialAmnesiaEvidence{VoteA: nil, VoteB: v2}, false, true},
{"&PotentialAmnesiaEvidence success", &PotentialAmnesiaEvidence{VoteA: v2, VoteB: v}, false, false},
{"&PhantomValidatorEvidence empty fail", &PhantomValidatorEvidence{}, false, true},
{"&PhantomValidatorEvidence nil LastHeightValidatorWasInSet", &PhantomValidatorEvidence{Vote: v}, false, true},
{"&PhantomValidatorEvidence nil Vote", &PhantomValidatorEvidence{LastHeightValidatorWasInSet: 2}, false, true},
{"PhantomValidatorEvidence success", PhantomValidatorEvidence{Vote: v2, LastHeightValidatorWasInSet: 2},
false, false},
}
for _, tt := range tests {
tt := tt

View File

@@ -128,7 +128,7 @@ func ValidateConsensusParams(params tmproto.ConsensusParams) error {
// Check if keyType is a known ABCIPubKeyType
for i := 0; i < len(params.Validator.PubKeyTypes); i++ {
keyType := params.Validator.PubKeyTypes[i]
if _, ok := ABCIPubKeyTypesToAminoNames[keyType]; !ok {
if _, ok := ABCIPubKeyTypesToNames[keyType]; !ok {
return fmt.Errorf("params.Validator.PubKeyTypes[%d], %s, is an unknown pubkey type",
i, keyType)
}

View File

@@ -30,10 +30,10 @@ const (
// TODO: Make non-global by allowing for registration of more pubkey types
var ABCIPubKeyTypesToAminoNames = map[string]string{
ABCIPubKeyTypeEd25519: ed25519.PubKeyAminoName,
ABCIPubKeyTypeSr25519: sr25519.PubKeyAminoName,
ABCIPubKeyTypeSecp256k1: secp256k1.PubKeyAminoName,
var ABCIPubKeyTypesToNames = map[string]string{
ABCIPubKeyTypeEd25519: ed25519.PubKeyName,
ABCIPubKeyTypeSr25519: sr25519.PubKeyName,
ABCIPubKeyTypeSecp256k1: secp256k1.PubKeyName,
}
//-------------------------------------------------------

View File

@@ -4,17 +4,13 @@ import (
"testing"
"time"
"github.com/gogo/protobuf/proto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
amino "github.com/tendermint/go-amino"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
cryptoenc "github.com/tendermint/tendermint/crypto/encoding"
"github.com/tendermint/tendermint/proto/version"
)
func TestABCIPubKey(t *testing.T) {
@@ -65,63 +61,6 @@ func TestABCIConsensusParams(t *testing.T) {
assert.Equal(t, *cp, cp2)
}
func newHeader(
height int64, commitHash, dataHash, evidenceHash []byte,
) *Header {
return &Header{
Height: height,
LastCommitHash: commitHash,
DataHash: dataHash,
EvidenceHash: evidenceHash,
}
}
func TestABCIHeader(t *testing.T) {
// build a full header
var height int64 = 5
header := newHeader(height, []byte("lastCommitHash"), []byte("dataHash"), []byte("evidenceHash"))
protocolVersion := version.Consensus{Block: 7, App: 8}
timestamp := time.Now()
lastBlockID := BlockID{
Hash: []byte("hash"),
PartsHeader: PartSetHeader{
Total: 10,
Hash: []byte("hash"),
},
}
header.Populate(
protocolVersion, "chainID", timestamp, lastBlockID,
[]byte("valHash"), []byte("nextValHash"),
[]byte("consHash"), []byte("appHash"), []byte("lastResultsHash"),
[]byte("proposerAddress"),
)
cdc := amino.NewCodec()
headerBz := cdc.MustMarshalBinaryBare(header)
pbHeader := header.ToProto()
pbHeaderBz, err := proto.Marshal(pbHeader)
assert.NoError(t, err)
// assert some fields match
assert.EqualValues(t, protocolVersion.Block, pbHeader.Version.Block)
assert.EqualValues(t, protocolVersion.App, pbHeader.Version.App)
assert.EqualValues(t, "chainID", pbHeader.ChainID)
assert.EqualValues(t, height, pbHeader.Height)
assert.EqualValues(t, timestamp, pbHeader.Time)
assert.EqualValues(t, lastBlockID.Hash, pbHeader.LastBlockId.Hash)
assert.EqualValues(t, []byte("lastCommitHash"), pbHeader.LastCommitHash)
assert.Equal(t, []byte("proposerAddress"), pbHeader.ProposerAddress)
// assert the encodings match
// NOTE: they don't yet because Amino encodes
// int64 as zig-zag and we're using non-zigzag in the protobuf.
// See https://github.com/tendermint/tendermint/issues/2682
_, _ = headerBz, pbHeaderBz
// assert.EqualValues(t, headerBz, pbHeaderBz)
}
func TestABCIEvidence(t *testing.T) {
val := NewMockPV()
blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))

View File

@@ -8,6 +8,7 @@ import (
"github.com/tendermint/tendermint/crypto/merkle"
"github.com/tendermint/tendermint/crypto/tmhash"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
tmproto "github.com/tendermint/tendermint/proto/types"
)
// Tx is an arbitrary byte array.
@@ -108,3 +109,31 @@ func (tp TxProof) Validate(dataHash []byte) error {
}
return nil
}
func (tp TxProof) ToProto() tmproto.TxProof {
pbProof := tp.Proof.ToProto()
pbtp := tmproto.TxProof{
RootHash: tp.RootHash,
Data: tp.Data,
Proof: pbProof,
}
return pbtp
}
func TxProofFromProto(pb tmproto.TxProof) (TxProof, error) {
pbProof, err := merkle.ProofFromProto(pb.Proof)
if err != nil {
return TxProof{}, err
}
pbtp := TxProof{
RootHash: pb.RootHash,
Data: pb.Data,
Proof: *pbProof,
}
return pbtp, nil
}

View File

@@ -5,9 +5,11 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
tmrand "github.com/tendermint/tendermint/libs/rand"
ctest "github.com/tendermint/tendermint/libs/test"
tmproto "github.com/tendermint/tendermint/proto/types"
)
func makeTxs(cnt, size int) Txs {
@@ -77,10 +79,18 @@ func TestValidTxProof(t *testing.T) {
assert.NotNil(t, proof.Validate([]byte("foobar")), "%d: %d", h, i)
// read-write must also work
var p2 TxProof
bin, err := cdc.MarshalBinaryLengthPrefixed(proof)
assert.Nil(t, err)
err = cdc.UnmarshalBinaryLengthPrefixed(bin, &p2)
var (
p2 TxProof
pb2 tmproto.TxProof
)
pbProof := proof.ToProto()
bin, err := pbProof.Marshal()
require.NoError(t, err)
err = pb2.Unmarshal(bin)
require.NoError(t, err)
p2, err = TxProofFromProto(pb2)
if assert.Nil(t, err, "%d: %d: %+v", h, i, err) {
assert.Nil(t, p2.Validate(root), "%d: %d", h, i)
}
@@ -104,8 +114,9 @@ func testTxProofUnchangable(t *testing.T) {
// make sure it is valid to start with
assert.Nil(t, proof.Validate(root))
bin, err := cdc.MarshalBinaryLengthPrefixed(proof)
assert.Nil(t, err)
pbProof := proof.ToProto()
bin, err := pbProof.Marshal()
require.NoError(t, err)
// try mutating the data and make sure nothing breaks
for j := 0; j < 500; j++ {
@@ -118,16 +129,23 @@ func testTxProofUnchangable(t *testing.T) {
// This makes sure that the proof doesn't deserialize into something valid.
func assertBadProof(t *testing.T, root []byte, bad []byte, good TxProof) {
var proof TxProof
err := cdc.UnmarshalBinaryLengthPrefixed(bad, &proof)
var (
proof TxProof
pbProof tmproto.TxProof
)
err := pbProof.Unmarshal(bad)
if err == nil {
err = proof.Validate(root)
proof, err = TxProofFromProto(pbProof)
if err == nil {
// XXX Fix simple merkle proofs so the following is *not* OK.
// This can happen if we have a slightly different total (where the
// path ends up the same). If it is something else, we have a real
// problem.
assert.NotEqual(t, proof.Proof.Total, good.Proof.Total, "bad: %#v\ngood: %#v", proof, good)
err = proof.Validate(root)
if err == nil {
// XXX Fix simple merkle proofs so the following is *not* OK.
// This can happen if we have a slightly different total (where the
// path ends up the same). If it is something else, we have a real
// problem.
assert.NotEqual(t, proof.Proof.Total, good.Proof.Total, "bad: %#v\ngood: %#v", proof, good)
}
}
}
}

View File

@@ -107,13 +107,21 @@ func ValidatorListString(vals []*Validator) string {
// as its redundant with the pubkey. This also excludes ProposerPriority
// which changes every round.
func (v *Validator) Bytes() []byte {
return cdcEncode(struct {
PubKey crypto.PubKey
VotingPower int64
}{
v.PubKey,
v.VotingPower,
})
pk, err := ce.PubKeyToProto(v.PubKey)
if err != nil {
panic(err)
}
pbv := tmproto.SimpleValidator{
PubKey: &pk,
VotingPower: v.VotingPower,
}
bz, err := pbv.Marshal()
if err != nil {
panic(err)
}
return bz
}
// ToProto converts Valiator to protobuf

View File

@@ -301,14 +301,17 @@ func TestProposerSelection2(t *testing.T) {
func TestProposerSelection3(t *testing.T) {
vset := NewValidatorSet([]*Validator{
newValidator([]byte("a"), 1),
newValidator([]byte("b"), 1),
newValidator([]byte("c"), 1),
newValidator([]byte("d"), 1),
newValidator([]byte("avalidator_address12"), 1),
newValidator([]byte("bvalidator_address12"), 1),
newValidator([]byte("cvalidator_address12"), 1),
newValidator([]byte("dvalidator_address12"), 1),
})
proposerOrder := make([]*Validator, 4)
for i := 0; i < 4; i++ {
// need to give all validators to have keys
pk := ed25519.GenPrivKey().PubKey()
vset.Validators[i].PubKey = pk
proposerOrder[i] = vset.GetProposer()
vset.IncrementProposerPriority(1)
}
@@ -329,7 +332,7 @@ func TestProposerSelection3(t *testing.T) {
// serialize, deserialize, check proposer
b := vset.toBytes()
vset.fromBytes(b)
vset = vset.fromBytes(b)
computed := vset.GetProposer() // findGetProposer()
if i != 0 {
@@ -388,19 +391,33 @@ func randValidatorSet(numValidators int) *ValidatorSet {
}
func (vals *ValidatorSet) toBytes() []byte {
bz, err := cdc.MarshalBinaryLengthPrefixed(vals)
pbvs, err := vals.ToProto()
if err != nil {
panic(err)
}
bz, err := pbvs.Marshal()
if err != nil {
panic(err)
}
return bz
}
func (vals *ValidatorSet) fromBytes(b []byte) {
err := cdc.UnmarshalBinaryLengthPrefixed(b, &vals)
func (vals *ValidatorSet) fromBytes(b []byte) *ValidatorSet {
pbvs := new(tmproto.ValidatorSet)
err := pbvs.Unmarshal(b)
if err != nil {
// DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
panic(err)
}
vs, err := ValidatorSetFromProto(pbvs)
if err != nil {
panic(err)
}
return vs
}
//-------------------------------------------------------------------