From 8ea73a293be6ba895f590f7dbb4bd4e8b9d26f06 Mon Sep 17 00:00:00 2001 From: Cyson Date: Sun, 14 May 2023 14:44:09 -0700 Subject: [PATCH] Revert block Evidence data type to nested Evidence --- internal/consensus/common_test.go | 2 +- internal/consensus/pbts_test.go | 2 +- internal/consensus/reactor_test.go | 2 +- internal/consensus/replay_test.go | 8 +-- internal/consensus/state.go | 6 +- internal/consensus/state_test.go | 14 ++--- internal/evidence/pool_test.go | 2 +- internal/state/execution.go | 16 ++--- internal/state/execution_test.go | 4 +- node/node_test.go | 2 +- test/e2e/tests/evidence_test.go | 4 +- types/block.go | 99 ++++++++++++++++++++++++++++-- types/block_test.go | 48 +++++++++++++-- types/events.go | 2 +- 14 files changed, 171 insertions(+), 40 deletions(-) diff --git a/internal/consensus/common_test.go b/internal/consensus/common_test.go index fc7e4af31..c5cdfc4e7 100644 --- a/internal/consensus/common_test.go +++ b/internal/consensus/common_test.go @@ -264,7 +264,7 @@ func decideProposal( address := pubKey.Address() polRound, propBlockID := validRound, types.BlockID{Hash: block.Hash(), PartSetHeader: blockParts.Header()} - proposal = types.NewProposal(height, round, polRound, propBlockID, block.Header.Time, block.GetTxKeys(), block.Header, block.LastCommit, block.Evidence, address) + proposal = types.NewProposal(height, round, polRound, propBlockID, block.Header.Time, block.GetTxKeys(), block.Header, block.LastCommit, block.Evidence.Evidence, address) p := proposal.ToProto() require.NoError(t, vs.SignProposal(ctx, chainID, p)) diff --git a/internal/consensus/pbts_test.go b/internal/consensus/pbts_test.go index 76f71cc7f..d75d97676 100644 --- a/internal/consensus/pbts_test.go +++ b/internal/consensus/pbts_test.go @@ -216,7 +216,7 @@ func (p *pbtsTestHarness) nextHeight(ctx context.Context, t *testing.T, proposer ps, err := b.MakePartSet(types.BlockPartSizeBytes) require.NoError(t, err) bid := types.BlockID{Hash: b.Hash(), PartSetHeader: ps.Header()} - prop := types.NewProposal(p.currentHeight, 0, -1, bid, proposedTime, b.GetTxKeys(), b.Header, b.LastCommit, b.Evidence, k.Address()) + prop := types.NewProposal(p.currentHeight, 0, -1, bid, proposedTime, b.GetTxKeys(), b.Header, b.LastCommit, b.Evidence.Evidence, k.Address()) tp := prop.ToProto() if err := proposer.SignProposal(ctx, p.observedState.state.ChainID, tp); err != nil { diff --git a/internal/consensus/reactor_test.go b/internal/consensus/reactor_test.go index 9220968d3..b01b89492 100644 --- a/internal/consensus/reactor_test.go +++ b/internal/consensus/reactor_test.go @@ -537,7 +537,7 @@ func TestReactorWithEvidence(t *testing.T) { } block := msg.Data().(types.EventDataNewBlock).Block - require.Len(t, block.Evidence, 1) + require.Len(t, block.Evidence.Evidence, 1) }(sub) } diff --git a/internal/consensus/replay_test.go b/internal/consensus/replay_test.go index 253a8c5d4..eb26df815 100644 --- a/internal/consensus/replay_test.go +++ b/internal/consensus/replay_test.go @@ -388,7 +388,7 @@ func setupSimulator(ctx context.Context, t *testing.T) *simulatorTestSuite { pubKey, err := vss[1].PrivValidator.GetPubKey(ctx) require.NoError(t, err) - proposal := types.NewProposal(vss[1].Height, round, -1, blockID, propBlock.Header.Time, propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence, pubKey.Address()) + proposal := types.NewProposal(vss[1].Height, round, -1, blockID, propBlock.Header.Time, propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence.Evidence, pubKey.Address()) p := proposal.ToProto() if err := vss[1].SignProposal(ctx, cfg.ChainID(), p); err != nil { t.Fatal("failed to sign bad proposal", err) @@ -423,7 +423,7 @@ func setupSimulator(ctx context.Context, t *testing.T) *simulatorTestSuite { blockID = types.BlockID{Hash: propBlock.Hash(), PartSetHeader: propBlockParts.Header()} pubKey, err = vss[2].PrivValidator.GetPubKey(ctx) require.NoError(t, err) - proposal = types.NewProposal(vss[1].Height, round, -1, blockID, propBlock.Header.Time, propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence, pubKey.Address()) + proposal = types.NewProposal(vss[1].Height, round, -1, blockID, propBlock.Header.Time, propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence.Evidence, pubKey.Address()) p = proposal.ToProto() if err := vss[2].SignProposal(ctx, cfg.ChainID(), p); err != nil { t.Fatal("failed to sign bad proposal", err) @@ -487,7 +487,7 @@ func setupSimulator(ctx context.Context, t *testing.T) *simulatorTestSuite { require.NotEqual(t, -1, selfIndex) pubKey, err = vss[3].PrivValidator.GetPubKey(ctx) require.NoError(t, err) - proposal = types.NewProposal(vss[3].Height, round, -1, blockID, propBlock.Header.Time, propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence, pubKey.Address()) + proposal = types.NewProposal(vss[3].Height, round, -1, blockID, propBlock.Header.Time, propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence.Evidence, pubKey.Address()) p = proposal.ToProto() if err := vss[3].SignProposal(ctx, cfg.ChainID(), p); err != nil { t.Fatal("failed to sign bad proposal", err) @@ -560,7 +560,7 @@ func setupSimulator(ctx context.Context, t *testing.T) *simulatorTestSuite { require.NotEqual(t, -1, selfIndex) pubKey, err = vss[1].PrivValidator.GetPubKey(ctx) require.NoError(t, err) - proposal = types.NewProposal(vss[1].Height, round, -1, blockID, propBlock.Header.Time, propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence, pubKey.Address()) + proposal = types.NewProposal(vss[1].Height, round, -1, blockID, propBlock.Header.Time, propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence.Evidence, pubKey.Address()) p = proposal.ToProto() if err := vss[1].SignProposal(ctx, cfg.ChainID(), p); err != nil { t.Fatal("failed to sign bad proposal", err) diff --git a/internal/consensus/state.go b/internal/consensus/state.go index 140fd4d5a..73827042f 100644 --- a/internal/consensus/state.go +++ b/internal/consensus/state.go @@ -1493,7 +1493,7 @@ func (cs *State) defaultDecideProposal(ctx context.Context, height int64, round // Make proposal propBlockID := types.BlockID{Hash: block.Hash(), PartSetHeader: blockParts.Header()} - proposal := types.NewProposal(height, round, cs.roundState.ValidRound(), propBlockID, block.Header.Time, block.GetTxKeys(), block.Header, block.LastCommit, block.Evidence, cs.privValidatorPubKey.Address()) + proposal := types.NewProposal(height, round, cs.roundState.ValidRound(), propBlockID, block.Header.Time, block.GetTxKeys(), block.Header, block.LastCommit, block.Evidence.Evidence, cs.privValidatorPubKey.Address()) p := proposal.ToProto() // wait the max amount we would wait for a proposal @@ -1647,7 +1647,7 @@ func (cs *State) defaultDoPrevote(ctx context.Context, height int64, round int32 return } // We have full proposal block and txs. Build proposal block with txKeys - proposalBlock := cs.buildProposalBlock(height, block.Header, block.LastCommit, block.Evidence, block.ProposerAddress, txKeys) + proposalBlock := cs.buildProposalBlock(height, block.Header, block.LastCommit, block.Evidence.Evidence, block.ProposerAddress, txKeys) if proposalBlock == nil { cs.signAddVote(ctx, tmproto.PrevoteType, nil, types.PartSetHeader{}) return @@ -2280,7 +2280,7 @@ func (cs *State) RecordMetrics(height int64, block *types.Block) { byzantineValidatorsCount int64 ) - for _, ev := range block.Evidence { + for _, ev := range block.Evidence.Evidence { if dve, ok := ev.(*types.DuplicateVoteEvidence); ok { if _, val := cs.roundState.Validators().GetByAddress(dve.VoteA.ValidatorAddress); val != nil { byzantineValidatorsCount++ diff --git a/internal/consensus/state_test.go b/internal/consensus/state_test.go index 7da622f16..2442eb935 100644 --- a/internal/consensus/state_test.go +++ b/internal/consensus/state_test.go @@ -239,7 +239,7 @@ func TestStateBadProposal(t *testing.T) { blockID := types.BlockID{Hash: propBlock.Hash(), PartSetHeader: propBlockParts.Header()} pubKey, err := vss[1].PrivValidator.GetPubKey(ctx) require.NoError(t, err) - proposal := types.NewProposal(vs2.Height, round, -1, blockID, propBlock.Header.Time, propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence, pubKey.Address()) + proposal := types.NewProposal(vs2.Height, round, -1, blockID, propBlock.Header.Time, propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence.Evidence, pubKey.Address()) p := proposal.ToProto() err = vs2.SignProposal(ctx, config.ChainID(), p) require.NoError(t, err) @@ -298,7 +298,7 @@ func TestStateOversizedBlock(t *testing.T) { blockID := types.BlockID{Hash: propBlock.Hash(), PartSetHeader: propBlockParts.Header()} pubKey, err := vss[1].PrivValidator.GetPubKey(ctx) require.NoError(t, err) - proposal := types.NewProposal(height, round, -1, blockID, propBlock.Header.Time, propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence, pubKey.Address()) + proposal := types.NewProposal(height, round, -1, blockID, propBlock.Header.Time, propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence.Evidence, pubKey.Address()) p := proposal.ToProto() err = vs2.SignProposal(ctx, config.ChainID(), p) require.NoError(t, err) @@ -808,7 +808,7 @@ func TestStateLock_POLRelock(t *testing.T) { round++ pubKey, err := vss[0].PrivValidator.GetPubKey(ctx) require.NoError(t, err) - propR1 := types.NewProposal(height, round, cs1.roundState.ValidRound(), blockID, theBlock.Header.Time, theBlock.GetTxKeys(), theBlock.Header, theBlock.LastCommit, theBlock.Evidence, pubKey.Address()) + propR1 := types.NewProposal(height, round, cs1.roundState.ValidRound(), blockID, theBlock.Header.Time, theBlock.GetTxKeys(), theBlock.Header, theBlock.LastCommit, theBlock.Evidence.Evidence, pubKey.Address()) p := propR1.ToProto() err = vs2.SignProposal(ctx, cs1.state.ChainID, p) require.NoError(t, err) @@ -1506,7 +1506,7 @@ func TestStateLock_POLSafety2(t *testing.T) { // in round 2 we see the polkad block from round 0 pubKey, err := vss[0].PrivValidator.GetPubKey(ctx) require.NoError(t, err) - newProp := types.NewProposal(height, round, 0, propBlockID0, propBlock0.Header.Time, propBlock0.GetTxKeys(), propBlock0.Header, propBlock0.LastCommit, propBlock0.Evidence, pubKey.Address()) + newProp := types.NewProposal(height, round, 0, propBlockID0, propBlock0.Header.Time, propBlock0.GetTxKeys(), propBlock0.Header, propBlock0.LastCommit, propBlock0.Evidence.Evidence, pubKey.Address()) p := newProp.ToProto() err = vs3.SignProposal(ctx, config.ChainID(), p) require.NoError(t, err) @@ -1647,7 +1647,7 @@ func TestState_PrevotePOLFromPreviousRound(t *testing.T) { round++ pubKey, err := vss[1].PrivValidator.GetPubKey(ctx) require.NoError(t, err) - propR2 := types.NewProposal(height, round, 1, r1BlockID, propBlockR1.Header.Time, propBlockR1.GetTxKeys(), propBlockR1.Header, propBlockR1.LastCommit, propBlockR1.Evidence, pubKey.Address()) + propR2 := types.NewProposal(height, round, 1, r1BlockID, propBlockR1.Header.Time, propBlockR1.GetTxKeys(), propBlockR1.Header, propBlockR1.LastCommit, propBlockR1.Evidence.Evidence, pubKey.Address()) p := propR2.ToProto() err = vs3.SignProposal(ctx, cs1.state.ChainID, p) require.NoError(t, err) @@ -3032,7 +3032,7 @@ func TestStateTimestamp_ProposalNotMatch(t *testing.T) { // Create a proposal with a timestamp that does not match the timestamp of the block. pubKey, err := vs2.PrivValidator.GetPubKey(ctx) require.NoError(t, err) - proposal := types.NewProposal(vs2.Height, round, -1, blockID, propBlock.Header.Time.Add(time.Millisecond), propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence, pubKey.Address()) + proposal := types.NewProposal(vs2.Height, round, -1, blockID, propBlock.Header.Time.Add(time.Millisecond), propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence.Evidence, pubKey.Address()) p := proposal.ToProto() err = vs2.SignProposal(ctx, config.ChainID(), p) require.NoError(t, err) @@ -3082,7 +3082,7 @@ func TestStateTimestamp_ProposalMatch(t *testing.T) { // Create a proposal with a timestamp that matches the timestamp of the block. pubKey, err := vs2.PrivValidator.GetPubKey(ctx) require.NoError(t, err) - proposal := types.NewProposal(vs2.Height, round, -1, blockID, propBlock.Header.Time, propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence, pubKey.Address()) + proposal := types.NewProposal(vs2.Height, round, -1, blockID, propBlock.Header.Time, propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence.Evidence, pubKey.Address()) p := proposal.ToProto() err = vs2.SignProposal(ctx, config.ChainID(), p) require.NoError(t, err) diff --git a/internal/evidence/pool_test.go b/internal/evidence/pool_test.go index f80d13c7b..6c0543379 100644 --- a/internal/evidence/pool_test.go +++ b/internal/evidence/pool_test.go @@ -268,7 +268,7 @@ func TestEvidencePoolUpdate(t *testing.T) { require.Equal(t, uint32(3), pool.Size()) - pool.Update(ctx, state, block.Evidence) + pool.Update(ctx, state, block.Evidence.Evidence) // a) Update marks evidence as committed so pending evidence should be empty evList, _ = pool.PendingEvidence(defaultEvidenceMaxBytes) diff --git a/internal/state/execution.go b/internal/state/execution.go index 540ef51e2..914b91fa8 100644 --- a/internal/state/execution.go +++ b/internal/state/execution.go @@ -110,7 +110,7 @@ func (blockExec *BlockExecutor) CreateProposalBlock( MaxTxBytes: maxDataBytes, Txs: block.Txs.ToSliceOfBytes(), LocalLastCommit: buildExtendedCommitInfo(lastExtCommit, blockExec.store, state.InitialHeight, state.ConsensusParams.ABCI), - ByzantineValidators: block.Evidence.ToABCI(), + ByzantineValidators: block.Evidence.Evidence.ToABCI(), Height: block.Height, Time: block.Time, NextValidatorsHash: block.NextValidatorsHash, @@ -169,7 +169,7 @@ func (blockExec *BlockExecutor) ProcessProposal( Time: block.Header.Time, Txs: txs, ProposedLastCommit: buildLastCommitInfo(block, blockExec.store, state.InitialHeight), - ByzantineValidators: block.Evidence.ToABCI(), + ByzantineValidators: block.Evidence.Evidence.ToABCI(), ProposerAddress: block.ProposerAddress, NextValidatorsHash: block.NextValidatorsHash, AppHash: block.AppHash, @@ -208,7 +208,7 @@ func (blockExec *BlockExecutor) ValidateBlock(ctx context.Context, state State, return err } - err = blockExec.evpool.CheckEvidence(ctx, block.Evidence) + err = blockExec.evpool.CheckEvidence(ctx, block.Evidence.Evidence) if err != nil { return err } @@ -254,7 +254,7 @@ func (blockExec *BlockExecutor) ApplyBlock( Time: block.Header.Time, Txs: txs, DecidedLastCommit: buildLastCommitInfo(block, blockExec.store, state.InitialHeight), - ByzantineValidators: block.Evidence.ToABCI(), + ByzantineValidators: block.Evidence.Evidence.ToABCI(), ProposerAddress: block.ProposerAddress, NextValidatorsHash: block.NextValidatorsHash, AppHash: block.AppHash, @@ -337,7 +337,7 @@ func (blockExec *BlockExecutor) ApplyBlock( } // Update evpool with the latest state. - blockExec.evpool.Update(ctx, state, block.Evidence) + blockExec.evpool.Update(ctx, state, block.Evidence.Evidence) // Update the app hash and save the state. state.AppHash = fBlockRes.AppHash @@ -711,8 +711,8 @@ func fireEvents( logger.Error("failed publishing new block header", "err", err) } - if len(block.Evidence) != 0 { - for _, ev := range block.Evidence { + if len(block.Evidence.Evidence) != 0 { + for _, ev := range block.Evidence.Evidence { if err := eventBus.PublishEventNewEvidence(types.EventDataNewEvidence{ Evidence: ev, Height: block.Height, @@ -772,7 +772,7 @@ func ExecCommitBlock( Time: block.Time, Txs: block.Txs.ToSliceOfBytes(), DecidedLastCommit: buildLastCommitInfo(block, store, initialHeight), - ByzantineValidators: block.Evidence.ToABCI(), + ByzantineValidators: block.Evidence.Evidence.ToABCI(), AppHash: block.AppHash, ValidatorsHash: block.ValidatorsHash, ConsensusHash: block.ConsensusHash, diff --git a/internal/state/execution_test.go b/internal/state/execution_test.go index 73804c4ca..f4122c784 100644 --- a/internal/state/execution_test.go +++ b/internal/state/execution_test.go @@ -266,7 +266,7 @@ func TestFinalizeBlockByzantineValidators(t *testing.T) { blockExec := sm.NewBlockExecutor(stateStore, log.NewNopLogger(), proxyApp, mp, evpool, blockStore, eventBus, sm.NopMetrics()) block := sf.MakeBlock(state, 1, new(types.Commit)) - block.Evidence = ev + block.Evidence = types.EvidenceData{Evidence: ev} block.Header.EvidenceHash = block.Evidence.Hash() bps, err := block.MakePartSet(testPartSize) require.NoError(t, err) @@ -347,7 +347,7 @@ func TestProcessProposal(t *testing.T) { Hash: block1.Hash(), Height: block1.Header.Height, Time: block1.Header.Time, - ByzantineValidators: block1.Evidence.ToABCI(), + ByzantineValidators: block1.Evidence.Evidence.ToABCI(), ProposedLastCommit: abci.CommitInfo{ Round: 0, Votes: voteInfos, diff --git a/node/node_test.go b/node/node_test.go index 314abf758..e04038af0 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -316,7 +316,7 @@ func TestCreateProposalBlock(t *testing.T) { evList, size := evidencePool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes) require.Less(t, size, state.ConsensusParams.Evidence.MaxBytes+1) - evData := types.EvidenceList(evList) + evData := &types.EvidenceData{Evidence: evList} require.EqualValues(t, size, evData.ByteSize()) // fill the mempool with more txs diff --git a/test/e2e/tests/evidence_test.go b/test/e2e/tests/evidence_test.go index a757c8550..9d0a1d255 100644 --- a/test/e2e/tests/evidence_test.go +++ b/test/e2e/tests/evidence_test.go @@ -17,8 +17,8 @@ func TestEvidence_Misbehavior(t *testing.T) { testnet := loadTestnet(t) seenEvidence := 0 for _, block := range blocks { - if len(block.Evidence) != 0 { - seenEvidence += len(block.Evidence) + if len(block.Evidence.Evidence) != 0 { + seenEvidence += len(block.Evidence.Evidence) } } require.Equal(t, testnet.Evidence, seenEvidence, diff --git a/types/block.go b/types/block.go index e2e0a955b..f5cb3d794 100644 --- a/types/block.go +++ b/types/block.go @@ -43,7 +43,7 @@ type Block struct { Header `json:"header"` Data `json:"data"` - Evidence EvidenceList `json:"evidence"` + Evidence EvidenceData `json:"evidence"` LastCommit *Commit `json:"last_commit"` } @@ -87,8 +87,8 @@ func (b *Block) ValidateBasic() error { return fmt.Errorf("wrong Header.DataHash. Expected %X, got %X. Len of txs %d", w, g, len(b.Data.Txs)) } - // NOTE: b.Evidence may be nil, but we're just looping. - for i, ev := range b.Evidence { + // NOTE: b.Evidence.Evidence may be nil, but we're just looping. + for i, ev := range b.Evidence.Evidence { if err := ev.ValidateBasic(); err != nil { return fmt.Errorf("invalid evidence (#%d): %v", i, err) } @@ -327,7 +327,7 @@ func MakeBlock(height int64, txs []Tx, lastCommit *Commit, evidence []Evidence) Data: Data{ Txs: txs, }, - Evidence: evidence, + Evidence: EvidenceData{Evidence: evidence}, LastCommit: lastCommit, } block.fillHeader() @@ -1372,6 +1372,97 @@ 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 diff --git a/types/block_test.go b/types/block_test.go index e55b7979e..47b92d1c3 100644 --- a/types/block_test.go +++ b/types/block_test.go @@ -51,7 +51,7 @@ func TestBlockAddEvidence(t *testing.T) { block := MakeBlock(h, txs, extCommit.ToCommit(), evList) require.NotNil(t, block) - require.Equal(t, 1, len(block.Evidence)) + require.Equal(t, 1, len(block.Evidence.Evidence)) require.NotNil(t, block.EvidenceHash) } @@ -111,7 +111,7 @@ func TestBlockValidateBasic(t *testing.T) { }, true}, {"Invalid Evidence", func(blk *Block) { emptyEv := &DuplicateVoteEvidence{} - blk.Evidence = []Evidence{emptyEv} + blk.Evidence = EvidenceData{Evidence: []Evidence{emptyEv}} }, true}, } for i, tc := range testCases { @@ -805,7 +805,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 = EvidenceList{evi} + b2.Evidence = EvidenceData{Evidence: EvidenceList{evi}} b2.EvidenceHash = b2.Evidence.Hash() b3 := MakeBlock(h, []Tx{}, c1, []Evidence{}) @@ -834,7 +834,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, block.Evidence, tc.msg) + require.EqualValues(t, tc.b1.Evidence.Evidence, block.Evidence.Evidence, tc.msg) require.EqualValues(t, *tc.b1.LastCommit, *block.LastCommit, tc.msg) } else { require.Error(t, err, tc.msg) @@ -842,6 +842,46 @@ func TestBlockProtoBuf(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) + } + } +} + func TestDataProtoBuf(t *testing.T) { data := &Data{Txs: Txs{Tx([]byte{1}), Tx([]byte{2}), Tx([]byte{3})}} data2 := &Data{Txs: Txs{}} diff --git a/types/events.go b/types/events.go index 62ce3dd3e..949c1cef6 100644 --- a/types/events.go +++ b/types/events.go @@ -198,7 +198,7 @@ func (e EventDataNewBlock) ToLegacy() LegacyEventData { block = &LegacyBlock{ Header: e.Block.Header, Data: e.Block.Data, - Evidence: LegacyEvidence{Evidence: e.Block.Evidence}, + Evidence: LegacyEvidence{Evidence: e.Block.Evidence.Evidence}, LastCommit: e.Block.LastCommit, } }