diff --git a/blockchain/reactor_test.go b/blockchain/reactor_test.go index 21eaae4b..11991bda 100644 --- a/blockchain/reactor_test.go +++ b/blockchain/reactor_test.go @@ -156,7 +156,7 @@ func makeTxs(height int64) (txs []types.Tx) { } func makeBlock(height int64, state sm.State) *types.Block { - block, _ := state.MakeBlock(height, makeTxs(height), new(types.Commit)) + block, _ := state.MakeBlock(height, makeTxs(height), new(types.Commit), nil) return block } diff --git a/consensus/state.go b/consensus/state.go index 634f1031..f66a872e 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -907,6 +907,8 @@ func (cs *ConsensusState) isProposalComplete() bool { } // Create the next block to propose and return it. +// We really only need to return the parts, but the block +// is returned for convenience so we can log the proposal block. // Returns nil block upon error. // NOTE: keep it side-effect free for clarity. func (cs *ConsensusState) createProposalBlock() (block *types.Block, blockParts *types.PartSet) { @@ -926,9 +928,8 @@ func (cs *ConsensusState) createProposalBlock() (block *types.Block, blockParts // Mempool validated transactions txs := cs.mempool.Reap(cs.state.ConsensusParams.BlockSize.MaxTxs) - block, parts := cs.state.MakeBlock(cs.Height, txs, commit) evidence := cs.evpool.PendingEvidence() - block.AddEvidence(evidence) + block, parts := cs.state.MakeBlock(cs.Height, txs, commit, evidence) return block, parts } diff --git a/state/execution_test.go b/state/execution_test.go index 81510fb9..d214ae4f 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -79,7 +79,7 @@ func TestBeginBlockValidators(t *testing.T) { lastCommit := &types.Commit{BlockID: prevBlockID, Precommits: tc.lastCommitPrecommits} // block for height 2 - block, _ := state.MakeBlock(2, makeTxs(2), lastCommit) + block, _ := state.MakeBlock(2, makeTxs(2), lastCommit, nil) _, err = ExecCommitBlock(proxyApp.Consensus(), block, log.TestingLogger(), state.Validators, stateDB) require.Nil(t, err, tc.desc) @@ -138,7 +138,7 @@ func TestBeginBlockByzantineValidators(t *testing.T) { lastCommit := &types.Commit{BlockID: prevBlockID, Precommits: votes} for _, tc := range testCases { - block, _ := state.MakeBlock(10, makeTxs(2), lastCommit) + block, _ := state.MakeBlock(10, makeTxs(2), lastCommit, nil) block.Time = now block.Evidence.Evidence = tc.evidence _, err = ExecCommitBlock(proxyApp.Consensus(), block, log.TestingLogger(), state.Validators, stateDB) @@ -269,7 +269,7 @@ func state(nVals, height int) (State, dbm.DB) { } func makeBlock(state State, height int64) *types.Block { - block, _ := state.MakeBlock(height, makeTxs(state.LastBlockHeight), new(types.Commit)) + block, _ := state.MakeBlock(height, makeTxs(state.LastBlockHeight), new(types.Commit), nil) return block } diff --git a/state/state.go b/state/state.go index 3bc08dae..fb589a24 100644 --- a/state/state.go +++ b/state/state.go @@ -101,18 +101,26 @@ func (state State) GetValidators() (last *types.ValidatorSet, current *types.Val //------------------------------------------------------------------------ // Create a block from the latest state -// MakeBlock builds a block with the given txs and commit from the current state. -func (state State) MakeBlock(height int64, txs []types.Tx, commit *types.Commit) (*types.Block, *types.PartSet) { - // build base block - block := types.MakeBlock(height, txs, commit) +// MakeBlock builds a block from the current state with the given txs, commit, and evidence. +func (state State) MakeBlock( + height int64, + txs []types.Tx, + commit *types.Commit, + evidence []types.Evidence, +) (*types.Block, *types.PartSet) { - // fill header with state data + // Build base block with block data. + block := types.MakeBlock(height, txs, commit, evidence) + + // Fill rest of header with state data. block.ChainID = state.ChainID - block.TotalTxs = state.LastBlockTotalTx + block.NumTxs + block.LastBlockID = state.LastBlockID + block.TotalTxs = state.LastBlockTotalTx + block.NumTxs + block.ValidatorsHash = state.Validators.Hash() - block.AppHash = state.AppHash block.ConsensusHash = state.ConsensusParams.Hash() + block.AppHash = state.AppHash block.LastResultsHash = state.LastResultsHash return block, block.MakePartSet(state.ConsensusParams.BlockGossip.BlockPartSizeBytes) diff --git a/types/block.go b/types/block.go index 48857076..304e8bde 100644 --- a/types/block.go +++ b/types/block.go @@ -25,7 +25,7 @@ type Block struct { // MakeBlock returns a new block with an empty header, except what can be computed from itself. // It populates the same set of fields validated by ValidateBasic -func MakeBlock(height int64, txs []Tx, commit *Commit) *Block { +func MakeBlock(height int64, txs []Tx, commit *Commit, evidence []Evidence) *Block { block := &Block{ Header: Header{ Height: height, @@ -35,20 +35,13 @@ func MakeBlock(height int64, txs []Tx, commit *Commit) *Block { Data: Data{ Txs: txs, }, + Evidence: EvidenceData{Evidence: evidence}, LastCommit: commit, } block.fillHeader() return block } -// AddEvidence appends the given evidence to the block -func (b *Block) AddEvidence(evidence []Evidence) { - if b == nil { - return - } - b.Evidence.Evidence = append(b.Evidence.Evidence, evidence...) -} - // ValidateBasic performs basic validation that doesn't involve state data. // It checks the internal consistency of the block. func (b *Block) ValidateBasic() error { diff --git a/types/block_test.go b/types/block_test.go index 1d27a774..714029bf 100644 --- a/types/block_test.go +++ b/types/block_test.go @@ -19,11 +19,13 @@ func TestBlockAddEvidence(t *testing.T) { commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals) require.NoError(t, err) - block := MakeBlock(h, txs, commit) - require.NotNil(t, block) - ev := NewMockGoodEvidence(h, 0, valSet.Validators[0].Address) - block.AddEvidence([]Evidence{ev}) + evList := []Evidence{ev} + + block := MakeBlock(h, txs, commit, evList) + require.NotNil(t, block) + require.Equal(t, 1, len(block.Evidence.Evidence)) + require.NotNil(t, block.EvidenceHash) } func TestBlockValidateBasic(t *testing.T) { @@ -33,11 +35,14 @@ func TestBlockValidateBasic(t *testing.T) { lastID := makeBlockIDRandom() h := int64(3) - voteSet, _, vals := randVoteSet(h-1, 1, VoteTypePrecommit, 10, 1) + voteSet, valSet, vals := randVoteSet(h-1, 1, VoteTypePrecommit, 10, 1) commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals) require.NoError(t, err) - block := MakeBlock(h, txs, commit) + ev := NewMockGoodEvidence(h, 0, valSet.Validators[0].Address) + evList := []Evidence{ev} + + block := MakeBlock(h, txs, commit, evList) require.NotNil(t, block) // proper block must pass @@ -45,39 +50,39 @@ func TestBlockValidateBasic(t *testing.T) { require.NoError(t, err) // tamper with NumTxs - block = MakeBlock(h, txs, commit) + block = MakeBlock(h, txs, commit, evList) block.NumTxs++ err = block.ValidateBasic() require.Error(t, err) // remove 1/2 the commits - block = MakeBlock(h, txs, commit) + block = MakeBlock(h, txs, commit, evList) block.LastCommit.Precommits = commit.Precommits[:commit.Size()/2] block.LastCommit.hash = nil // clear hash or change wont be noticed err = block.ValidateBasic() require.Error(t, err) // tamper with LastCommitHash - block = MakeBlock(h, txs, commit) + block = MakeBlock(h, txs, commit, evList) block.LastCommitHash = []byte("something else") err = block.ValidateBasic() require.Error(t, err) // tamper with data - block = MakeBlock(h, txs, commit) + block = MakeBlock(h, txs, commit, evList) block.Data.Txs[0] = Tx("something else") block.Data.hash = nil // clear hash or change wont be noticed err = block.ValidateBasic() require.Error(t, err) // tamper with DataHash - block = MakeBlock(h, txs, commit) + block = MakeBlock(h, txs, commit, evList) block.DataHash = cmn.RandBytes(len(block.DataHash)) err = block.ValidateBasic() require.Error(t, err) // tamper with evidence - block = MakeBlock(h, txs, commit) + block = MakeBlock(h, txs, commit, evList) block.EvidenceHash = []byte("something else") err = block.ValidateBasic() require.Error(t, err) @@ -85,13 +90,13 @@ func TestBlockValidateBasic(t *testing.T) { func TestBlockHash(t *testing.T) { assert.Nil(t, (*Block)(nil).Hash()) - assert.Nil(t, MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil).Hash()) + assert.Nil(t, MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).Hash()) } func TestBlockMakePartSet(t *testing.T) { assert.Nil(t, (*Block)(nil).MakePartSet(2)) - partSet := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil).MakePartSet(1024) + partSet := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).MakePartSet(1024) assert.NotNil(t, partSet) assert.Equal(t, 1, partSet.Total()) } @@ -105,7 +110,10 @@ func TestBlockHashesTo(t *testing.T) { commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals) require.NoError(t, err) - block := MakeBlock(h, []Tx{Tx("Hello World")}, commit) + ev := NewMockGoodEvidence(h, 0, valSet.Validators[0].Address) + evList := []Evidence{ev} + + block := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList) block.ValidatorsHash = valSet.Hash() assert.False(t, block.HashesTo([]byte{})) assert.False(t, block.HashesTo([]byte("something else"))) @@ -113,7 +121,7 @@ func TestBlockHashesTo(t *testing.T) { } func TestBlockSize(t *testing.T) { - size := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil).Size() + size := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).Size() if size <= 0 { t.Fatal("Size of the block is zero or negative") } @@ -124,7 +132,7 @@ func TestBlockString(t *testing.T) { assert.Equal(t, "nil-Block", (*Block)(nil).StringIndented("")) assert.Equal(t, "nil-Block", (*Block)(nil).StringShort()) - block := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil) + block := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil) assert.NotEqual(t, "nil-Block", block.String()) assert.NotEqual(t, "nil-Block", block.StringIndented("")) assert.NotEqual(t, "nil-Block", block.StringShort())