mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-05 04:55:18 +00:00
types: remove nested evidence field from block (#7765)
* types: replaced EvidenceData in block structure with EvidenceList * types: introduced toProto, fromProto functions to EvidenceList * updated Changelog * Removed comments from tests
This commit is contained in:
committed by
GitHub
parent
a9fa2ac5f9
commit
cd875c8a2c
@@ -44,7 +44,7 @@ type Block struct {
|
||||
|
||||
Header `json:"header"`
|
||||
Data `json:"data"`
|
||||
Evidence EvidenceData `json:"evidence"`
|
||||
Evidence EvidenceList `json:"evidence"`
|
||||
LastCommit *Commit `json:"last_commit"`
|
||||
}
|
||||
|
||||
@@ -80,8 +80,8 @@ func (b *Block) ValidateBasic() error {
|
||||
return fmt.Errorf("wrong Header.DataHash. Expected %X, got %X", w, g)
|
||||
}
|
||||
|
||||
// NOTE: b.Evidence.Evidence may be nil, but we're just looping.
|
||||
for i, ev := range b.Evidence.Evidence {
|
||||
// NOTE: b.Evidence may be nil, but we're just looping.
|
||||
for i, ev := range b.Evidence {
|
||||
if err := ev.ValidateBasic(); err != nil {
|
||||
return fmt.Errorf("invalid evidence (#%d): %v", i, err)
|
||||
}
|
||||
@@ -316,7 +316,7 @@ func MakeBlock(height int64, txs []Tx, lastCommit *Commit, evidence []Evidence)
|
||||
Data: Data{
|
||||
Txs: txs,
|
||||
},
|
||||
Evidence: EvidenceData{Evidence: evidence},
|
||||
Evidence: evidence,
|
||||
LastCommit: lastCommit,
|
||||
}
|
||||
block.fillHeader()
|
||||
@@ -1083,97 +1083,6 @@ func DataFromProto(dp *tmproto.Data) (Data, error) {
|
||||
return *data, nil
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// EvidenceData contains any evidence of malicious wrong-doing by validators
|
||||
type EvidenceData struct {
|
||||
Evidence EvidenceList `json:"evidence"`
|
||||
|
||||
// Volatile. Used as cache
|
||||
hash tmbytes.HexBytes
|
||||
byteSize int64
|
||||
}
|
||||
|
||||
// Hash returns the hash of the data.
|
||||
func (data *EvidenceData) Hash() tmbytes.HexBytes {
|
||||
if data.hash == nil {
|
||||
data.hash = data.Evidence.Hash()
|
||||
}
|
||||
return data.hash
|
||||
}
|
||||
|
||||
// ByteSize returns the total byte size of all the evidence
|
||||
func (data *EvidenceData) ByteSize() int64 {
|
||||
if data.byteSize == 0 && len(data.Evidence) != 0 {
|
||||
pb, err := data.ToProto()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
data.byteSize = int64(pb.Size())
|
||||
}
|
||||
return data.byteSize
|
||||
}
|
||||
|
||||
// StringIndented returns a string representation of the evidence.
|
||||
func (data *EvidenceData) StringIndented(indent string) string {
|
||||
if data == nil {
|
||||
return "nil-Evidence"
|
||||
}
|
||||
evStrings := make([]string, tmmath.MinInt(len(data.Evidence), 21))
|
||||
for i, ev := range data.Evidence {
|
||||
if i == 20 {
|
||||
evStrings[i] = fmt.Sprintf("... (%v total)", len(data.Evidence))
|
||||
break
|
||||
}
|
||||
evStrings[i] = fmt.Sprintf("Evidence:%v", ev)
|
||||
}
|
||||
return fmt.Sprintf(`EvidenceData{
|
||||
%s %v
|
||||
%s}#%v`,
|
||||
indent, strings.Join(evStrings, "\n"+indent+" "),
|
||||
indent, data.hash)
|
||||
}
|
||||
|
||||
// ToProto converts EvidenceData to protobuf
|
||||
func (data *EvidenceData) ToProto() (*tmproto.EvidenceList, error) {
|
||||
if data == nil {
|
||||
return nil, errors.New("nil evidence data")
|
||||
}
|
||||
|
||||
evi := new(tmproto.EvidenceList)
|
||||
eviBzs := make([]tmproto.Evidence, len(data.Evidence))
|
||||
for i := range data.Evidence {
|
||||
protoEvi, err := EvidenceToProto(data.Evidence[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
eviBzs[i] = *protoEvi
|
||||
}
|
||||
evi.Evidence = eviBzs
|
||||
|
||||
return evi, nil
|
||||
}
|
||||
|
||||
// FromProto sets a protobuf EvidenceData to the given pointer.
|
||||
func (data *EvidenceData) FromProto(eviData *tmproto.EvidenceList) error {
|
||||
if eviData == nil {
|
||||
return errors.New("nil evidenceData")
|
||||
}
|
||||
|
||||
eviBzs := make(EvidenceList, len(eviData.Evidence))
|
||||
for i := range eviData.Evidence {
|
||||
evi, err := EvidenceFromProto(&eviData.Evidence[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eviBzs[i] = evi
|
||||
}
|
||||
data.Evidence = eviBzs
|
||||
data.byteSize = int64(eviData.Size())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
// BlockID
|
||||
|
||||
@@ -52,7 +52,7 @@ func TestBlockAddEvidence(t *testing.T) {
|
||||
|
||||
block := MakeBlock(h, txs, commit, evList)
|
||||
require.NotNil(t, block)
|
||||
require.Equal(t, 1, len(block.Evidence.Evidence))
|
||||
require.Equal(t, 1, len(block.Evidence))
|
||||
require.NotNil(t, block.EvidenceHash)
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ func TestBlockValidateBasic(t *testing.T) {
|
||||
}, true},
|
||||
{"Invalid Evidence", func(blk *Block) {
|
||||
emptyEv := &DuplicateVoteEvidence{}
|
||||
blk.Evidence = EvidenceData{Evidence: []Evidence{emptyEv}}
|
||||
blk.Evidence = []Evidence{emptyEv}
|
||||
}, true},
|
||||
}
|
||||
for i, tc := range testCases {
|
||||
@@ -700,7 +700,7 @@ func TestBlockProtoBuf(t *testing.T) {
|
||||
evidenceTime := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
evi, err := NewMockDuplicateVoteEvidence(ctx, h, evidenceTime, "block-test-chain")
|
||||
require.NoError(t, err)
|
||||
b2.Evidence = EvidenceData{Evidence: EvidenceList{evi}}
|
||||
b2.Evidence = EvidenceList{evi}
|
||||
b2.EvidenceHash = b2.Evidence.Hash()
|
||||
|
||||
b3 := MakeBlock(h, []Tx{}, c1, []Evidence{})
|
||||
@@ -729,7 +729,7 @@ func TestBlockProtoBuf(t *testing.T) {
|
||||
require.NoError(t, err, tc.msg)
|
||||
require.EqualValues(t, tc.b1.Header, block.Header, tc.msg)
|
||||
require.EqualValues(t, tc.b1.Data, block.Data, tc.msg)
|
||||
require.EqualValues(t, tc.b1.Evidence.Evidence, block.Evidence.Evidence, tc.msg)
|
||||
require.EqualValues(t, tc.b1.Evidence, block.Evidence, tc.msg)
|
||||
require.EqualValues(t, *tc.b1.LastCommit, *block.LastCommit, tc.msg)
|
||||
} else {
|
||||
require.Error(t, err, tc.msg)
|
||||
@@ -760,46 +760,6 @@ func TestDataProtoBuf(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestEvidenceDataProtoBuf ensures parity in converting to and from proto.
|
||||
func TestEvidenceDataProtoBuf(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
const chainID = "mychain"
|
||||
ev, err := NewMockDuplicateVoteEvidence(ctx, math.MaxInt64, time.Now(), chainID)
|
||||
require.NoError(t, err)
|
||||
data := &EvidenceData{Evidence: EvidenceList{ev}}
|
||||
_ = data.ByteSize()
|
||||
testCases := []struct {
|
||||
msg string
|
||||
data1 *EvidenceData
|
||||
expPass1 bool
|
||||
expPass2 bool
|
||||
}{
|
||||
{"success", data, true, true},
|
||||
{"empty evidenceData", &EvidenceData{Evidence: EvidenceList{}}, true, true},
|
||||
{"fail nil Data", nil, false, false},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
protoData, err := tc.data1.ToProto()
|
||||
if tc.expPass1 {
|
||||
require.NoError(t, err, tc.msg)
|
||||
} else {
|
||||
require.Error(t, err, tc.msg)
|
||||
}
|
||||
|
||||
eviD := new(EvidenceData)
|
||||
err = eviD.FromProto(protoData)
|
||||
if tc.expPass2 {
|
||||
require.NoError(t, err, tc.msg)
|
||||
require.Equal(t, tc.data1, eviD, tc.msg)
|
||||
} else {
|
||||
require.Error(t, err, tc.msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// exposed for testing
|
||||
func MakeRandHeader() Header {
|
||||
chainID := "test"
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/tendermint/tendermint/crypto/merkle"
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
"github.com/tendermint/tendermint/internal/jsontypes"
|
||||
tmmath "github.com/tendermint/tendermint/libs/math"
|
||||
tmrand "github.com/tendermint/tendermint/libs/rand"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
)
|
||||
@@ -554,6 +555,73 @@ func LightClientAttackEvidenceFromProto(lpb *tmproto.LightClientAttackEvidence)
|
||||
// EvidenceList is a list of Evidence. Evidences is not a word.
|
||||
type EvidenceList []Evidence
|
||||
|
||||
// StringIndented returns a string representation of the evidence.
|
||||
func (evl EvidenceList) StringIndented(indent string) string {
|
||||
if evl == nil {
|
||||
return "nil-Evidence"
|
||||
}
|
||||
evStrings := make([]string, tmmath.MinInt(len(evl), 21))
|
||||
for i, ev := range evl {
|
||||
if i == 20 {
|
||||
evStrings[i] = fmt.Sprintf("... (%v total)", len(evl))
|
||||
break
|
||||
}
|
||||
evStrings[i] = fmt.Sprintf("Evidence:%v", ev)
|
||||
}
|
||||
return fmt.Sprintf(`EvidenceList{
|
||||
%s %v
|
||||
%s}#%v`,
|
||||
indent, strings.Join(evStrings, "\n"+indent+" "),
|
||||
indent, evl.Hash())
|
||||
}
|
||||
|
||||
// ByteSize returns the total byte size of all the evidence
|
||||
func (evl EvidenceList) ByteSize() int64 {
|
||||
if len(evl) != 0 {
|
||||
pb, err := evl.ToProto()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return int64(pb.Size())
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// FromProto sets a protobuf EvidenceList to the given pointer.
|
||||
func (evl *EvidenceList) FromProto(eviList *tmproto.EvidenceList) error {
|
||||
if eviList == nil {
|
||||
return errors.New("nil evidence list")
|
||||
}
|
||||
|
||||
eviBzs := make(EvidenceList, len(eviList.Evidence))
|
||||
for i := range eviList.Evidence {
|
||||
evi, err := EvidenceFromProto(&eviList.Evidence[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eviBzs[i] = evi
|
||||
}
|
||||
*evl = eviBzs
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToProto converts EvidenceList to protobuf
|
||||
func (evl *EvidenceList) ToProto() (*tmproto.EvidenceList, error) {
|
||||
if evl == nil {
|
||||
return nil, errors.New("nil evidence list")
|
||||
}
|
||||
|
||||
eviBzs := make([]tmproto.Evidence, len(*evl))
|
||||
for i, v := range *evl {
|
||||
protoEvi, err := EvidenceToProto(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
eviBzs[i] = *protoEvi
|
||||
}
|
||||
return &tmproto.EvidenceList{Evidence: eviBzs}, nil
|
||||
}
|
||||
|
||||
func (evl EvidenceList) MarshalJSON() ([]byte, error) {
|
||||
lst := make([]json.RawMessage, len(evl))
|
||||
for i, ev := range evl {
|
||||
|
||||
@@ -33,6 +33,44 @@ func TestEvidenceList(t *testing.T) {
|
||||
assert.False(t, evl.Has(&DuplicateVoteEvidence{}))
|
||||
}
|
||||
|
||||
// TestEvidenceListProtoBuf to ensure parity in protobuf output and input
|
||||
func TestEvidenceListProtoBuf(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
const chainID = "mychain"
|
||||
ev, err := NewMockDuplicateVoteEvidence(ctx, math.MaxInt64, time.Now(), chainID)
|
||||
require.NoError(t, err)
|
||||
data := EvidenceList{ev}
|
||||
testCases := []struct {
|
||||
msg string
|
||||
data1 *EvidenceList
|
||||
expPass1 bool
|
||||
expPass2 bool
|
||||
}{
|
||||
{"success", &data, true, true},
|
||||
{"empty evidenceData", &EvidenceList{}, true, true},
|
||||
{"fail nil Data", nil, false, false},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
protoData, err := tc.data1.ToProto()
|
||||
if tc.expPass1 {
|
||||
require.NoError(t, err, tc.msg)
|
||||
} else {
|
||||
require.Error(t, err, tc.msg)
|
||||
}
|
||||
|
||||
eviD := new(EvidenceList)
|
||||
err = eviD.FromProto(protoData)
|
||||
if tc.expPass2 {
|
||||
require.NoError(t, err, tc.msg)
|
||||
require.Equal(t, tc.data1, eviD, tc.msg)
|
||||
} else {
|
||||
require.Error(t, err, tc.msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
func randomDuplicateVoteEvidence(ctx context.Context, t *testing.T) *DuplicateVoteEvidence {
|
||||
t.Helper()
|
||||
val := NewMockPV()
|
||||
|
||||
Reference in New Issue
Block a user