Skip to content

Commit

Permalink
beef up block#ValidateBasic
Browse files Browse the repository at this point in the history
  • Loading branch information
melekes committed Oct 30, 2018
1 parent 2059361 commit 7f919df
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 41 deletions.
2 changes: 1 addition & 1 deletion config/toml.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ func ResetTestRoot(testName string) *Config {
}

var testGenesis = `{
"genesis_time": "2017-10-10T08:20:13.695936996Z",
"genesis_time": "2018-10-10T08:20:13.695936996Z",
"chain_id": "tendermint_test",
"validators": [
{
Expand Down
2 changes: 0 additions & 2 deletions consensus/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -610,8 +610,6 @@ func randGenesisDoc(numValidators int, randPower bool, minPower int64) (*types.G
func randGenesisState(numValidators int, randPower bool, minPower int64) (sm.State, []types.PrivValidator) {
genDoc, privValidators := randGenesisDoc(numValidators, randPower, minPower)
s0, _ := sm.MakeGenesisState(genDoc)
db := dbm.NewMemDB() // remove this ?
sm.SaveState(db, s0)
return s0, privValidators
}

Expand Down
1 change: 0 additions & 1 deletion consensus/mempool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (

"github.com/tendermint/tendermint/abci/example/code"
abci "github.com/tendermint/tendermint/abci/types"

"github.com/tendermint/tendermint/types"
)

Expand Down
4 changes: 1 addition & 3 deletions state/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"errors"
"fmt"

"github.com/tendermint/tendermint/crypto/tmhash"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/types"
)
Expand Down Expand Up @@ -158,8 +157,7 @@ func validateBlock(stateDB dbm.DB, state State, block *types.Block) error {
// NOTE: We can't actually verify it's the right proposer because we dont
// know what round the block was first proposed. So just check that it's
// a legit address and a known validator.
if len(block.ProposerAddress) != tmhash.Size ||
!state.Validators.HasAddress(block.ProposerAddress) {
if !state.Validators.HasAddress(block.ProposerAddress) {
return fmt.Errorf(
"Block.Header.ProposerAddress, %X, is not a validator",
block.ProposerAddress,
Expand Down
82 changes: 63 additions & 19 deletions types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ package types

import (
"bytes"
"errors"
"fmt"
"strings"
"sync"
"time"

"github.com/pkg/errors"

"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/merkle"
"github.com/tendermint/tendermint/crypto/tmhash"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/tendermint/tendermint/version"
)
Expand Down Expand Up @@ -60,52 +61,98 @@ func MakeBlock(height int64, txs []Tx, lastCommit *Commit, evidence []Evidence)
// It checks the internal consistency of the block.
func (b *Block) ValidateBasic() error {
if b == nil {
return errors.New("Nil blocks are invalid")
return errors.New("nil block")
}
b.mtx.Lock()
defer b.mtx.Unlock()

if b.Height < 0 {
return fmt.Errorf("Negative Block.Header.Height: %v", b.Height)
return errors.New("Negative Header.Height")
}

if err := ValidateTime(b.Time); err != nil {
return err
}

// Validate num txs.
newTxs := int64(len(b.Data.Txs))
if b.NumTxs != newTxs {
return fmt.Errorf("Wrong Block.Header.NumTxs. Expected %v, got %v",
return fmt.Errorf("Wrong Header.NumTxs. Expected %v, got %v",
newTxs,
b.NumTxs,
)
}
if b.TotalTxs < b.NumTxs {
return errors.New("Header.TotalTxs is less than Header.NumTxs")
}

if !bytes.Equal(b.LastCommitHash, b.LastCommit.Hash()) {
return fmt.Errorf("Wrong Block.Header.LastCommitHash. Expected %v, got %v",
b.LastCommitHash,
b.LastCommit.Hash(),
)
if err := b.LastBlockID.ValidateBasic(); err != nil {
return fmt.Errorf("Wrong Header.LastBlockID: %v", err)
}

// Validate evidence.
for _, ev := range b.Evidence.Evidence {
if err := ev.ValidateBasic(); err != nil {
return err
}
}

// Validate hashes.
if b.Header.Height != 1 {
if b.LastCommit == nil {
return errors.New("nil LastCommit")
}
if err := b.LastCommit.ValidateBasic(); err != nil {
return err
}
}

if err := ValidateHash(b.LastCommitHash); err != nil {
return errors.Wrap(err, "Wrong Header.LastCommitHash")
}
if !bytes.Equal(b.LastCommitHash, b.LastCommit.Hash()) {
return fmt.Errorf("Wrong Header.LastCommitHash. Expected %v, got %v",
b.LastCommitHash,
b.LastCommit.Hash(),
)
}
if err := ValidateHash(b.DataHash); err != nil {
return errors.Wrap(err, "Wrong Header.DataHash")
}
if !bytes.Equal(b.DataHash, b.Data.Hash()) {
return fmt.Errorf(
"Wrong Block.Header.DataHash. Expected %v, got %v",
"Wrong Header.DataHash. Expected %v, got %v",
b.DataHash,
b.Data.Hash(),
)
}

if err := ValidateHash(b.ValidatorsHash); err != nil {
return errors.Wrap(err, "Wrong Header.ValidatorsHash")
}
if err := ValidateHash(b.NextValidatorsHash); err != nil {
return errors.Wrap(err, "Wrong Header.NextValidatorsHash")
}
if err := ValidateHash(b.ConsensusHash); err != nil {
return errors.Wrap(err, "Wrong Header.ConsensusHash")
}
if err := ValidateHash(b.LastResultsHash); err != nil {
return errors.Wrap(err, "Wrong Header.LastResultsHash")
}
if err := ValidateHash(b.EvidenceHash); err != nil {
return errors.Wrap(err, "Wrong Header.EvidenceHash")
}
if !bytes.Equal(b.EvidenceHash, b.Evidence.Hash()) {
return fmt.Errorf(
"Wrong Block.Header.EvidenceHash. Expected %v, got %v",
"Wrong Header.EvidenceHash. Expected %v, got %v",
b.EvidenceHash,
b.Evidence.Hash(),
)
}

if len(b.ProposerAddress) != crypto.AddressSize {
return fmt.Errorf("Expected len(Header.ProposerAddress) to be %d",
crypto.AddressSize)
}

return nil
}

Expand Down Expand Up @@ -723,11 +770,8 @@ func (blockID BlockID) Key() string {
// ValidateBasic performs basic validation.
func (blockID BlockID) ValidateBasic() error {
// Hash can be empty in case of POLBlockID in Proposal.
if len(blockID.Hash) > 0 && len(blockID.Hash) != tmhash.Size {
return fmt.Errorf("Expected Hash size to be %d bytes, got %d bytes",
tmhash.Size,
len(blockID.Hash),
)
if err := ValidateHash(blockID.Hash); err != nil {
return errors.Wrap(err, "Wrong Hash")
}
if err := blockID.PartsHeader.ValidateBasic(); err != nil {
return fmt.Errorf("Wrong PartsHeader: %v", err)
Expand Down
10 changes: 4 additions & 6 deletions types/part_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package types

import (
"bytes"
"errors"
"fmt"
"io"
"sync"

"github.com/pkg/errors"

"github.com/tendermint/tendermint/crypto/merkle"
"github.com/tendermint/tendermint/crypto/tmhash"
cmn "github.com/tendermint/tendermint/libs/common"
Expand Down Expand Up @@ -87,11 +88,8 @@ func (psh PartSetHeader) ValidateBasic() error {
return errors.New("Negative Total")
}
// Hash can be empty in case of POLBlockID.PartsHeader in Proposal.
if len(psh.Hash) > 0 && len(psh.Hash) != tmhash.Size {
return fmt.Errorf("Expected Hash size to be %d bytes, got %d bytes",
tmhash.Size,
len(psh.Hash),
)
if err := ValidateHash(psh.Hash); err != nil {
return errors.Wrap(err, "Wrong Hash")
}
return nil
}
Expand Down
6 changes: 2 additions & 4 deletions types/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,8 @@ func (p *Proposal) ValidateBasic() error {
if p.Round < 0 {
return errors.New("Negative Round")
}
now := tmtime.Now()
oneYear := 8766 * time.Hour
if p.Timestamp.Before(now.Add(-oneYear)) || p.Timestamp.After(now.Add(oneYear)) {
return fmt.Errorf("Time drifted too much. Expected: -1 < %v < 1 year", now)
if err := ValidateTime(p.Timestamp); err != nil {
return err
}
if err := p.BlockPartsHeader.ValidateBasic(); err != nil {
return fmt.Errorf("Wrong BlockPartsHeader: %v", err)
Expand Down
34 changes: 34 additions & 0 deletions types/validation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package types

import (
"fmt"
"time"

"github.com/tendermint/tendermint/crypto/tmhash"
tmtime "github.com/tendermint/tendermint/types/time"
)

// ValidateTime does a basic time validation ensuring time does not drift too
// much: +/- one year.
func ValidateTime(t time.Time) error {
var (
now = tmtime.Now()
oneYear = 8766 * time.Hour
)
if t.Before(now.Add(-oneYear)) || t.After(now.Add(oneYear)) {
return fmt.Errorf("Time drifted too much. Expected: -1 < %v < 1 year", now)
}
return nil
}

// ValidateHash returns an error if the hash is not empty, but its
// size != tmhash.Size.
func ValidateHash(h []byte) error {
if len(h) > 0 && len(h) != tmhash.Size {
return fmt.Errorf("Expected size to be %d bytes, got %d bytes",
tmhash.Size,
len(h),
)
}
return nil
}
7 changes: 2 additions & 5 deletions types/vote.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

"github.com/tendermint/tendermint/crypto"
cmn "github.com/tendermint/tendermint/libs/common"
tmtime "github.com/tendermint/tendermint/types/time"
)

const (
Expand Down Expand Up @@ -127,10 +126,8 @@ func (vote *Vote) ValidateBasic() error {
if vote.Round < 0 {
return errors.New("Negative Round")
}
now := tmtime.Now()
oneYear := 8766 * time.Hour
if vote.Timestamp.Before(now.Add(-oneYear)) || vote.Timestamp.After(now.Add(oneYear)) {
return fmt.Errorf("Time drifted too much. Expected: -1 < %v < 1 year", now)
if err := ValidateTime(vote.Timestamp); err != nil {
return err
}
if !IsVoteTypeValid(vote.Type) {
return errors.New("Invalid Type")
Expand Down

0 comments on commit 7f919df

Please sign in to comment.