diff --git a/blockchain/reactor_test.go b/blockchain/reactor_test.go index e652df3fd..d3e341644 100644 --- a/blockchain/reactor_test.go +++ b/blockchain/reactor_test.go @@ -112,6 +112,7 @@ func makeBlock(height int64, state *sm.State) *types.Block { block, _ := types.MakeBlock(height, "test_chain", makeTxs(height), state.LastBlockTotalTx, new(types.Commit), prevBlockID, valHash, state.AppHash, + state.Params.Hash(), state.Params.BlockGossipParams.BlockPartSizeBytes) return block } diff --git a/consensus/state.go b/consensus/state.go index 8a2692a22..1018d3704 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -866,7 +866,8 @@ func (cs *ConsensusState) createProposalBlock() (block *types.Block, blockParts return types.MakeBlock(cs.Height, cs.state.ChainID, txs, cs.state.LastBlockTotalTx, commit, cs.state.LastBlockID, cs.state.Validators.Hash(), - cs.state.AppHash, cs.state.Params.BlockPartSizeBytes) + cs.state.AppHash, cs.state.Params.Hash(), + cs.state.Params.BlockPartSizeBytes) } // Enter: `timeoutPropose` after entering Propose. diff --git a/state/execution.go b/state/execution.go index 6f6a7ca18..fbb0954d3 100644 --- a/state/execution.go +++ b/state/execution.go @@ -187,7 +187,7 @@ func (s *State) ValidateBlock(block *types.Block) error { func (s *State) validateBlock(block *types.Block) error { // Basic block validation. err := block.ValidateBasic(s.ChainID, s.LastBlockHeight, - s.LastBlockTotalTx, s.LastBlockID, s.LastBlockTime, s.AppHash) + s.LastBlockTotalTx, s.LastBlockID, s.LastBlockTime, s.AppHash, s.Params.Hash()) if err != nil { return err } diff --git a/state/execution_test.go b/state/execution_test.go index ac5c72f26..081a71e91 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -120,7 +120,7 @@ func makeBlock(height int64, state *State) *types.Block { block, _ := types.MakeBlock(height, chainID, makeTxs(height), state.LastBlockTotalTx, new(types.Commit), prevBlockID, valHash, - state.AppHash, testPartSize) + state.AppHash, state.Params.Hash(), testPartSize) return block } diff --git a/state/state.go b/state/state.go index 94ca05281..d3bca4a81 100644 --- a/state/state.go +++ b/state/state.go @@ -269,8 +269,9 @@ func (s *State) SetBlockAndValidators(header *types.Header, blockPartsHeader typ } -// applyChanges returns a new param set, overriding any -// parameter that is non-zero in argument +// applyChanges returns new ConsensusParams +// whose fields are set to any non-zero fields of c. +// If c is nil, it returns p unmodified, as it was passed in. func applyChanges(p types.ConsensusParams, c *abci.ConsensusParams) types.ConsensusParams { diff --git a/types/block.go b/types/block.go index ff3d3811b..356776579 100644 --- a/types/block.go +++ b/types/block.go @@ -25,7 +25,7 @@ type Block struct { // TODO: Add version information to the Block struct. func MakeBlock(height int64, chainID string, txs []Tx, totalTxs int64, commit *Commit, - prevBlockID BlockID, valHash, appHash []byte, + prevBlockID BlockID, valHash, appHash, consensusHash []byte, partSize int) (*Block, *PartSet) { newTxs := int64(len(txs)) @@ -39,6 +39,7 @@ func MakeBlock(height int64, chainID string, txs []Tx, LastBlockID: prevBlockID, ValidatorsHash: valHash, AppHash: appHash, // state merkle root of txs from the previous block. + ConsensusHash: consensusHash, }, LastCommit: commit, Data: &Data{ @@ -52,7 +53,7 @@ func MakeBlock(height int64, chainID string, txs []Tx, // ValidateBasic performs basic validation that doesn't involve state data. func (b *Block) ValidateBasic(chainID string, lastBlockHeight int64, lastBlockTotalTx int64, lastBlockID BlockID, - lastBlockTime time.Time, appHash []byte) error { + lastBlockTime time.Time, appHash, consensusHash []byte) error { if b.ChainID != chainID { return errors.New(cmn.Fmt("Wrong Block.Header.ChainID. Expected %v, got %v", chainID, b.ChainID)) @@ -91,6 +92,13 @@ func (b *Block) ValidateBasic(chainID string, lastBlockHeight int64, if !bytes.Equal(b.AppHash, appHash) { return errors.New(cmn.Fmt("Wrong Block.Header.AppHash. Expected %X, got %v", appHash, b.AppHash)) } + // TODO: make testing easier + if len(consensusHash) == 0 { + panic("food") + } + if !bytes.Equal(b.ConsensusHash, consensusHash) { + return errors.New(cmn.Fmt("Wrong Block.Header.ConsensusHash. Expected %X, got %v", consensusHash, b.ConsensusHash)) + } // NOTE: the AppHash and ValidatorsHash are validated later. return nil } @@ -178,6 +186,7 @@ type Header struct { DataHash data.Bytes `json:"data_hash"` // transactions ValidatorsHash data.Bytes `json:"validators_hash"` // validators for the current block AppHash data.Bytes `json:"app_hash"` // state after txs from the previous block + ConsensusHash data.Bytes `json:"consensus_hash"` // consensus params for current block } // Hash returns the hash of the header. @@ -197,6 +206,7 @@ func (h *Header) Hash() data.Bytes { "Data": h.DataHash, "Validators": h.ValidatorsHash, "App": h.AppHash, + "Consensus": h.ConsensusHash, }) } @@ -216,6 +226,7 @@ func (h *Header) StringIndented(indent string) string { %s Data: %v %s Validators: %v %s App: %v +%s Conensus: %v %s}#%v`, indent, h.ChainID, indent, h.Height, @@ -227,6 +238,7 @@ func (h *Header) StringIndented(indent string) string { indent, h.DataHash, indent, h.ValidatorsHash, indent, h.AppHash, + indent, h.ConsensusHash, indent, h.Hash()) } diff --git a/types/block_test.go b/types/block_test.go index 25e5a76e7..a874508a4 100644 --- a/types/block_test.go +++ b/types/block_test.go @@ -13,6 +13,7 @@ func TestValidateBlock(t *testing.T) { lastID := makeBlockID() valHash := []byte("val") appHash := []byte("app") + consensusHash := []byte("consensus-params") h := int64(3) voteSet, _, vals := randVoteSet(h-1, 1, VoteTypePrecommit, @@ -21,33 +22,36 @@ func TestValidateBlock(t *testing.T) { require.NoError(t, err) block, _ := MakeBlock(h, "hello", txs, 10, commit, - lastID, valHash, appHash, 2) + lastID, valHash, appHash, consensusHash, 2) require.NotNil(t, block) // proper block must pass - err = block.ValidateBasic("hello", h-1, 10, lastID, block.Time, appHash) + err = block.ValidateBasic("hello", h-1, 10, lastID, block.Time, appHash, consensusHash) require.NoError(t, err) // wrong chain fails - err = block.ValidateBasic("other", h-1, 10, lastID, block.Time, appHash) + err = block.ValidateBasic("other", h-1, 10, lastID, block.Time, appHash, consensusHash) require.Error(t, err) // wrong height fails - err = block.ValidateBasic("hello", h+4, 10, lastID, block.Time, appHash) + err = block.ValidateBasic("hello", h+4, 10, lastID, block.Time, appHash, consensusHash) require.Error(t, err) // wrong total tx fails - err = block.ValidateBasic("hello", h-1, 15, lastID, block.Time, appHash) + err = block.ValidateBasic("hello", h-1, 15, lastID, block.Time, appHash, consensusHash) require.Error(t, err) // wrong blockid fails - err = block.ValidateBasic("hello", h-1, 10, makeBlockID(), block.Time, appHash) + err = block.ValidateBasic("hello", h-1, 10, makeBlockID(), block.Time, appHash, consensusHash) require.Error(t, err) // wrong app hash fails - err = block.ValidateBasic("hello", h-1, 10, lastID, block.Time, []byte("bad-hash")) + err = block.ValidateBasic("hello", h-1, 10, lastID, block.Time, []byte("bad-hash"), consensusHash) require.Error(t, err) + // wrong consensus hash fails + err = block.ValidateBasic("hello", h-1, 10, lastID, block.Time, appHash, []byte("wrong-params")) + require.Error(t, err) } func makeBlockID() BlockID {