mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-08 06:15:33 +00:00
ADR-016: Add versions to Block and State (#2644)
* types: add Version to Header * abci: add Version to Header * state: add Version to State * node: check software and state protocol versions match * update changelog * docs/spec: update for versions * state: more tests * remove TODOs * remove empty test
This commit is contained in:
@@ -398,9 +398,13 @@ func updateState(
|
||||
lastHeightParamsChanged = header.Height + 1
|
||||
}
|
||||
|
||||
// TODO: allow app to upgrade version
|
||||
nextVersion := state.Version
|
||||
|
||||
// NOTE: the AppHash has not been populated.
|
||||
// It will be filled on state.Save.
|
||||
return State{
|
||||
Version: nextVersion,
|
||||
ChainID: state.ChainID,
|
||||
LastBlockHeight: header.Height,
|
||||
LastBlockTotalTx: state.LastBlockTotalTx + header.NumTxs,
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/tendermint/tendermint/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
"github.com/tendermint/tendermint/version"
|
||||
)
|
||||
|
||||
// database keys
|
||||
@@ -17,6 +18,25 @@ var (
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Version is for versioning the State.
|
||||
// It holds the Block and App version needed for making blocks,
|
||||
// and the software version to support upgrades to the format of
|
||||
// the State as stored on disk.
|
||||
type Version struct {
|
||||
Consensus version.Consensus
|
||||
Software string
|
||||
}
|
||||
|
||||
var initStateVersion = Version{
|
||||
Consensus: version.Consensus{
|
||||
Block: version.BlockProtocol,
|
||||
App: 0,
|
||||
},
|
||||
Software: version.TMCoreSemVer,
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// State is a short description of the latest committed block of the Tendermint consensus.
|
||||
// It keeps all information necessary to validate new blocks,
|
||||
// including the last validator set and the consensus params.
|
||||
@@ -25,6 +45,8 @@ var (
|
||||
// Instead, use state.Copy() or state.NextState(...).
|
||||
// NOTE: not goroutine-safe.
|
||||
type State struct {
|
||||
Version Version
|
||||
|
||||
// immutable
|
||||
ChainID string
|
||||
|
||||
@@ -59,6 +81,7 @@ type State struct {
|
||||
// Copy makes a copy of the State for mutating.
|
||||
func (state State) Copy() State {
|
||||
return State{
|
||||
Version: state.Version,
|
||||
ChainID: state.ChainID,
|
||||
|
||||
LastBlockHeight: state.LastBlockHeight,
|
||||
@@ -114,6 +137,7 @@ func (state State) MakeBlock(
|
||||
block := types.MakeBlock(height, txs, commit, evidence)
|
||||
|
||||
// Fill rest of header with state data.
|
||||
block.Version = state.Version.Consensus
|
||||
block.ChainID = state.ChainID
|
||||
|
||||
// Set time
|
||||
@@ -217,7 +241,7 @@ func MakeGenesisState(genDoc *types.GenesisDoc) (State, error) {
|
||||
}
|
||||
|
||||
return State{
|
||||
|
||||
Version: initStateVersion,
|
||||
ChainID: genDoc.ChainID,
|
||||
|
||||
LastBlockHeight: 0,
|
||||
|
||||
@@ -319,9 +319,11 @@ func TestStateMakeBlock(t *testing.T) {
|
||||
defer tearDown(t)
|
||||
|
||||
proposerAddress := state.Validators.GetProposer().Address
|
||||
stateVersion := state.Version.Consensus
|
||||
block := makeBlock(state, 2)
|
||||
|
||||
// test we set proposer address
|
||||
// test we set some fields
|
||||
assert.Equal(t, stateVersion, block.Version)
|
||||
assert.Equal(t, proposerAddress, block.ProposerAddress)
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,13 @@ func validateBlock(stateDB dbm.DB, state State, block *types.Block) error {
|
||||
}
|
||||
|
||||
// Validate basic info.
|
||||
if block.Version != state.Version.Consensus {
|
||||
return fmt.Errorf(
|
||||
"Wrong Block.Header.Version. Expected %v, got %v",
|
||||
state.Version.Consensus,
|
||||
block.Version,
|
||||
)
|
||||
}
|
||||
if block.ChainID != state.ChainID {
|
||||
return fmt.Errorf(
|
||||
"Wrong Block.Header.ChainID. Expected %v, got %v",
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
@@ -26,13 +27,20 @@ func TestValidateBlockHeader(t *testing.T) {
|
||||
err := blockExec.ValidateBlock(state, block)
|
||||
require.NoError(t, err)
|
||||
|
||||
// some bad values
|
||||
wrongHash := tmhash.Sum([]byte("this hash is wrong"))
|
||||
wrongVersion1 := state.Version.Consensus
|
||||
wrongVersion1.Block += 1
|
||||
wrongVersion2 := state.Version.Consensus
|
||||
wrongVersion2.App += 1
|
||||
|
||||
// Manipulation of any header field causes failure.
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleateBlock func(block *types.Block)
|
||||
}{
|
||||
{"Version wrong1", func(block *types.Block) { block.Version = wrongVersion1 }},
|
||||
{"Version wrong2", func(block *types.Block) { block.Version = wrongVersion2 }},
|
||||
{"ChainID wrong", func(block *types.Block) { block.ChainID = "not-the-real-one" }},
|
||||
{"Height wrong", func(block *types.Block) { block.Height += 10 }},
|
||||
{"Time wrong", func(block *types.Block) { block.Time = block.Time.Add(-time.Second * 3600 * 24) }},
|
||||
|
||||
Reference in New Issue
Block a user