Browse Source

header: check block protocol (#5340)

## Description

Check block protocol version in header validate basic. 

I tried searching for where we check the P2P protocol version but was unable to find it. When we check compatibility with a node we check we both have the same block protocol and are on the same network, but we do not check if we are on the same P2P protocol. It makes sense if there is a handshake change because we would not be able to establish a secure connection, but a p2p protocol version bump may be because of a p2p message change, which would go unnoticed until that message is sent over the wire.  Is this purposeful?

Closes: #4790
pull/5346/head
Marko 4 years ago
committed by GitHub
parent
commit
6ab2a19088
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 39 additions and 11 deletions
  1. +1
    -0
      CHANGELOG_PENDING.md
  2. +2
    -1
      blockchain/msgs_test.go
  3. +3
    -0
      light/helpers_test.go
  4. +3
    -0
      light/store/db/db_test.go
  5. +7
    -1
      store/store_test.go
  6. +4
    -0
      types/block.go
  7. +10
    -6
      types/block_test.go
  8. +5
    -2
      types/light_test.go
  9. +4
    -1
      types/test_util.go

+ 1
- 0
CHANGELOG_PENDING.md View File

@ -35,6 +35,7 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
- [blockchain] \#5278 Verify only +2/3 of the signatures in a block when fast syncing. (@marbar3778)
- [rpc] \#5293 `/dial_peers` has added `private` and `unconditional` as parameters. (@marbar3778)
- [types] \#5340 Add check in `Header.ValidateBasic()` for block protocol version (@marbar3778)
## BUG FIXES


+ 2
- 1
blockchain/msgs_test.go View File

@ -81,6 +81,7 @@ func TestBcStatusResponseMessageValidateBasic(t *testing.T) {
// nolint:lll // ignore line length in tests
func TestBlockchainMessageVectors(t *testing.T) {
block := types.MakeBlock(int64(3), []types.Tx{types.Tx("Hello World")}, nil, nil)
block.Version.Block = 11 // overwrite updated protocol version
bpb, err := block.ToProto()
require.NoError(t, err)
@ -96,7 +97,7 @@ func TestBlockchainMessageVectors(t *testing.T) {
BlockRequest: &bcproto.BlockRequest{Height: math.MaxInt64}}},
"0a0a08ffffffffffffffff7f"},
{"BlockResponseMessage", &bcproto.Message{Sum: &bcproto.Message_BlockResponse{
BlockResponse: &bcproto.BlockResponse{Block: bpb}}}, "1ab3010ab0010a590a001803220b088092b8c398feffffff012a0212003a20c4da88e876062aa1543400d50d0eaa0dac88096057949cfb7bca7f3a48c04bf96a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855122f0a0b48656c6c6f20576f726c641220c4da88e876062aa1543400d50d0eaa0dac88096057949cfb7bca7f3a48c04bf91a221220e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"},
BlockResponse: &bcproto.BlockResponse{Block: bpb}}}, "1ab5010ab2010a5b0a02080b1803220b088092b8c398feffffff012a0212003a20c4da88e876062aa1543400d50d0eaa0dac88096057949cfb7bca7f3a48c04bf96a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855122f0a0b48656c6c6f20576f726c641220c4da88e876062aa1543400d50d0eaa0dac88096057949cfb7bca7f3a48c04bf91a221220e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"},
{"NoBlockResponseMessage", &bcproto.Message{Sum: &bcproto.Message_NoBlockResponse{
NoBlockResponse: &bcproto.NoBlockResponse{Height: 1}}}, "12020801"},
{"NoBlockResponseMessage", &bcproto.Message{Sum: &bcproto.Message_NoBlockResponse{


+ 3
- 0
light/helpers_test.go View File

@ -7,8 +7,10 @@ import (
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/tmhash"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
"github.com/tendermint/tendermint/types"
tmtime "github.com/tendermint/tendermint/types/time"
"github.com/tendermint/tendermint/version"
)
// privKeys is a helper type for testing.
@ -126,6 +128,7 @@ func genHeader(chainID string, height int64, bTime time.Time, txs types.Txs,
valset, nextValset *types.ValidatorSet, appHash, consHash, resHash []byte) *types.Header {
return &types.Header{
Version: tmversion.Consensus{Block: version.BlockProtocol, App: 0},
ChainID: chainID,
Height: height,
Time: bTime,


+ 3
- 0
light/store/db/db_test.go View File

@ -13,7 +13,9 @@ import (
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/tmhash"
tmrand "github.com/tendermint/tendermint/libs/rand"
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
"github.com/tendermint/tendermint/types"
"github.com/tendermint/tendermint/version"
)
func TestLast_FirstLightBlockHeight(t *testing.T) {
@ -173,6 +175,7 @@ func randLightBlock(height int64) *types.LightBlock {
return &types.LightBlock{
SignedHeader: &types.SignedHeader{
Header: &types.Header{
Version: tmversion.Consensus{Block: version.BlockProtocol, App: 0},
ChainID: tmrand.Str(12),
Height: height,
Time: time.Now(),


+ 7
- 1
store/store_test.go View File

@ -19,9 +19,11 @@ import (
"github.com/tendermint/tendermint/libs/log"
tmrand "github.com/tendermint/tendermint/libs/rand"
tmstore "github.com/tendermint/tendermint/proto/tendermint/store"
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
sm "github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types"
tmtime "github.com/tendermint/tendermint/types/time"
"github.com/tendermint/tendermint/version"
)
// A cleanupFunc cleans up any config / test files created for a particular
@ -182,6 +184,7 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) {
require.Error(t, err)
header1 := types.Header{
Version: tmversion.Consensus{Block: version.BlockProtocol},
Height: 1,
ChainID: "block_test",
Time: tmtime.Now(),
@ -218,6 +221,7 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) {
{
block: newBlock( // New block at height 5 in empty block store is fine
types.Header{
Version: tmversion.Consensus{Block: version.BlockProtocol},
Height: 5,
ChainID: "block_test",
Time: tmtime.Now(),
@ -502,7 +506,9 @@ func TestLoadBlockMeta(t *testing.T) {
require.Contains(t, panicErr.Error(), "unmarshal to tmproto.BlockMeta")
// 3. A good blockMeta serialized and saved to the DB should be retrievable
meta := &types.BlockMeta{Header: types.Header{Height: 1, ProposerAddress: tmrand.Bytes(crypto.AddressSize)}}
meta := &types.BlockMeta{Header: types.Header{
Version: tmversion.Consensus{
Block: version.BlockProtocol, App: 0}, Height: 1, ProposerAddress: tmrand.Bytes(crypto.AddressSize)}}
pbm := meta.ToProto()
err = db.Set(calcBlockMetaKey(height), mustEncode(pbm))
require.NoError(t, err)


+ 4
- 0
types/block.go View File

@ -19,6 +19,7 @@ import (
tmsync "github.com/tendermint/tendermint/libs/sync"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
"github.com/tendermint/tendermint/version"
)
const (
@ -375,6 +376,9 @@ func (h *Header) Populate(
//
// NOTE: Timestamp validation is subtle and handled elsewhere.
func (h Header) ValidateBasic() error {
if h.Version.Block != version.BlockProtocol {
return fmt.Errorf("block protocol is incorrect: got: %d, want: %d ", h.Version.Block, version.BlockProtocol)
}
if len(h.ChainID) > MaxChainIDLen {
return fmt.Errorf("chainID is too long; got: %d, max: %d", len(h.ChainID), MaxChainIDLen)
}


+ 10
- 6
types/block_test.go View File

@ -22,8 +22,9 @@ import (
"github.com/tendermint/tendermint/libs/bytes"
tmrand "github.com/tendermint/tendermint/libs/rand"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/tendermint/tendermint/proto/tendermint/version"
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
tmtime "github.com/tendermint/tendermint/types/time"
"github.com/tendermint/tendermint/version"
)
func TestMain(m *testing.M) {
@ -86,6 +87,9 @@ func TestBlockValidateBasic(t *testing.T) {
{"Tampered EvidenceHash", func(blk *Block) {
blk.EvidenceHash = []byte("something else")
}, true},
{"Incorrect block protocol version", func(blk *Block) {
blk.Version.Block = 1
}, true},
}
for i, tc := range testCases {
tc := tc
@ -260,7 +264,7 @@ func TestHeaderHash(t *testing.T) {
expectHash bytes.HexBytes
}{
{"Generates expected hash", &Header{
Version: version.Consensus{Block: 1, App: 2},
Version: tmversion.Consensus{Block: 1, App: 2},
ChainID: "chainId",
Height: 3,
Time: time.Date(2019, 10, 13, 16, 14, 44, 0, time.UTC),
@ -277,7 +281,7 @@ func TestHeaderHash(t *testing.T) {
}, hexBytesFromString("F740121F553B5418C3EFBD343C2DBFE9E007BB67B0D020A0741374BAB65242A4")},
{"nil header yields nil", nil, nil},
{"nil ValidatorsHash yields nil", &Header{
Version: version.Consensus{Block: 1, App: 2},
Version: tmversion.Consensus{Block: 1, App: 2},
ChainID: "chainId",
Height: 3,
Time: time.Date(2019, 10, 13, 16, 14, 44, 0, time.UTC),
@ -317,7 +321,7 @@ func TestHeaderHash(t *testing.T) {
bz, err := gogotypes.StdTimeMarshal(f)
require.NoError(t, err)
byteSlices = append(byteSlices, bz)
case version.Consensus:
case tmversion.Consensus:
bz, err := f.Marshal()
require.NoError(t, err)
byteSlices = append(byteSlices, bz)
@ -352,7 +356,7 @@ func TestMaxHeaderBytes(t *testing.T) {
timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC)
h := Header{
Version: version.Consensus{Block: math.MaxInt64, App: math.MaxInt64},
Version: tmversion.Consensus{Block: math.MaxInt64, App: math.MaxInt64},
ChainID: maxChainID,
Height: math.MaxInt64,
Time: timestamp,
@ -696,7 +700,7 @@ func makeRandHeader() Header {
randBytes := tmrand.Bytes(tmhash.Size)
randAddress := tmrand.Bytes(crypto.AddressSize)
h := Header{
Version: version.Consensus{Block: 1, App: 1},
Version: tmversion.Consensus{Block: version.BlockProtocol, App: 1},
ChainID: chainID,
Height: height,
Time: t,


+ 5
- 2
types/light_test.go View File

@ -8,7 +8,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/proto/tendermint/version"
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
"github.com/tendermint/tendermint/version"
)
func TestLightBlockValidateBasic(t *testing.T) {
@ -18,6 +19,7 @@ func TestLightBlockValidateBasic(t *testing.T) {
header.Height = commit.Height
header.LastBlockID = commit.BlockID
header.ValidatorsHash = vals.Hash()
header.Version.Block = version.BlockProtocol
vals2, _ := RandValidatorSet(3, 1)
vals3 := vals.Copy()
vals3.Proposer = &Validator{}
@ -61,6 +63,7 @@ func TestLightBlockProtobuf(t *testing.T) {
vals, _ := RandValidatorSet(5, 1)
header.Height = commit.Height
header.LastBlockID = commit.BlockID
header.Version.Block = version.BlockProtocol
header.ValidatorsHash = vals.Hash()
vals3 := vals.Copy()
vals3.Proposer = &Validator{}
@ -112,7 +115,7 @@ func TestSignedHeaderValidateBasic(t *testing.T) {
chainID := "𠜎"
timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC)
h := Header{
Version: version.Consensus{Block: math.MaxInt64, App: math.MaxInt64},
Version: tmversion.Consensus{Block: version.BlockProtocol, App: math.MaxInt64},
ChainID: chainID,
Height: commit.Height,
Time: timestamp,


+ 4
- 1
types/test_util.go View File

@ -5,6 +5,8 @@ import (
"time"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
"github.com/tendermint/tendermint/version"
)
func MakeCommit(blockID BlockID, height int64, round int32,
@ -85,7 +87,8 @@ func MakeVote(
func MakeBlock(height int64, txs []Tx, lastCommit *Commit, evidence []Evidence) *Block {
block := &Block{
Header: Header{
Height: height,
Version: tmversion.Consensus{Block: version.BlockProtocol, App: 0},
Height: height,
},
Data: Data{
Txs: txs,


Loading…
Cancel
Save