Merge branch 'master' into jae/verifyingcachineprovider

This commit is contained in:
Anton Kaliaev
2019-08-14 16:03:33 +04:00
283 changed files with 12322 additions and 8008 deletions
+1 -20
View File
@@ -41,25 +41,6 @@ type Block struct {
LastCommit *Commit `json:"last_commit"`
}
// 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, lastCommit *Commit, evidence []Evidence) *Block {
block := &Block{
Header: Header{
Height: height,
NumTxs: int64(len(txs)),
},
Data: Data{
Txs: txs,
},
Evidence: EvidenceData{Evidence: evidence},
LastCommit: lastCommit,
}
block.fillHeader()
return block
}
// ValidateBasic performs basic validation that doesn't involve state data.
// It checks the internal consistency of the block.
// Further validation is done using state#ValidateBlock.
@@ -800,7 +781,7 @@ func (sh SignedHeader) ValidateBasic(chainID string) error {
// ValidateBasic on the Commit.
err := sh.Commit.ValidateBasic()
if err != nil {
return cmn.ErrorWrap(err, "commit.ValidateBasic failed during SignedHeader.ValidateBasic")
return errors.Wrap(err, "commit.ValidateBasic failed during SignedHeader.ValidateBasic")
}
return nil
}
+88
View File
@@ -366,3 +366,91 @@ func TestCommitToVoteSet(t *testing.T) {
assert.Equal(t, vote1bz, vote3bz)
}
}
func TestSignedHeaderValidateBasic(t *testing.T) {
commit := randCommit()
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},
ChainID: chainID,
Height: commit.Height(),
Time: timestamp,
NumTxs: math.MaxInt64,
TotalTxs: math.MaxInt64,
LastBlockID: commit.BlockID,
LastCommitHash: commit.Hash(),
DataHash: commit.Hash(),
ValidatorsHash: commit.Hash(),
NextValidatorsHash: commit.Hash(),
ConsensusHash: commit.Hash(),
AppHash: commit.Hash(),
LastResultsHash: commit.Hash(),
EvidenceHash: commit.Hash(),
ProposerAddress: crypto.AddressHash([]byte("proposer_address")),
}
validSignedHeader := SignedHeader{Header: &h, Commit: commit}
validSignedHeader.Commit.BlockID.Hash = validSignedHeader.Hash()
invalidSignedHeader := SignedHeader{}
testCases := []struct {
testName string
shHeader *Header
shCommit *Commit
expectErr bool
}{
{"Valid Signed Header", validSignedHeader.Header, validSignedHeader.Commit, false},
{"Invalid Signed Header", invalidSignedHeader.Header, validSignedHeader.Commit, true},
{"Invalid Signed Header", validSignedHeader.Header, invalidSignedHeader.Commit, true},
}
for _, tc := range testCases {
t.Run(tc.testName, func(t *testing.T) {
sh := SignedHeader{
Header: tc.shHeader,
Commit: tc.shCommit,
}
assert.Equal(t, tc.expectErr, sh.ValidateBasic(validSignedHeader.Header.ChainID) != nil, "Validate Basic had an unexpected result")
})
}
}
func TestBlockIDValidateBasic(t *testing.T) {
validBlockID := BlockID{
Hash: cmn.HexBytes{},
PartsHeader: PartSetHeader{
Total: 1,
Hash: cmn.HexBytes{},
},
}
invalidBlockID := BlockID{
Hash: []byte{0},
PartsHeader: PartSetHeader{
Total: -1,
Hash: cmn.HexBytes{},
},
}
testCases := []struct {
testName string
blockIDHash cmn.HexBytes
blockIDPartsHeader PartSetHeader
expectErr bool
}{
{"Valid BlockID", validBlockID.Hash, validBlockID.PartsHeader, false},
{"Invalid BlockID", invalidBlockID.Hash, validBlockID.PartsHeader, true},
{"Invalid BlockID", validBlockID.Hash, invalidBlockID.PartsHeader, true},
}
for _, tc := range testCases {
t.Run(tc.testName, func(t *testing.T) {
blockID := BlockID{
Hash: tc.blockIDHash,
PartsHeader: tc.blockIDPartsHeader,
}
assert.Equal(t, tc.expectErr, blockID.ValidateBasic() != nil, "Validate Basic had an unexpected result")
})
}
}
View File
+10
View File
@@ -157,3 +157,13 @@ func TestDuplicateVoteEvidenceValidation(t *testing.T) {
})
}
}
func TestMockGoodEvidenceValidateBasic(t *testing.T) {
goodEvidence := NewMockGoodEvidence(int64(1), 1, []byte{1})
assert.Nil(t, goodEvidence.ValidateBasic())
}
func TestMockBadEvidenceValidateBasic(t *testing.T) {
badEvidence := MockBadEvidence{MockGoodEvidence: NewMockGoodEvidence(int64(1), 1, []byte{1})}
assert.Nil(t, badEvidence.ValidateBasic())
}
+10 -10
View File
@@ -7,6 +7,8 @@ import (
"io/ioutil"
"time"
"github.com/pkg/errors"
"github.com/tendermint/tendermint/crypto"
cmn "github.com/tendermint/tendermint/libs/common"
tmtime "github.com/tendermint/tendermint/types/time"
@@ -64,26 +66,24 @@ func (genDoc *GenesisDoc) ValidatorHash() []byte {
// and fills in defaults for optional fields left empty
func (genDoc *GenesisDoc) ValidateAndComplete() error {
if genDoc.ChainID == "" {
return cmn.NewError("Genesis doc must include non-empty chain_id")
return errors.New("Genesis doc must include non-empty chain_id")
}
if len(genDoc.ChainID) > MaxChainIDLen {
return cmn.NewError("chain_id in genesis doc is too long (max: %d)", MaxChainIDLen)
return errors.Errorf("chain_id in genesis doc is too long (max: %d)", MaxChainIDLen)
}
if genDoc.ConsensusParams == nil {
genDoc.ConsensusParams = DefaultConsensusParams()
} else {
if err := genDoc.ConsensusParams.Validate(); err != nil {
return err
}
} else if err := genDoc.ConsensusParams.Validate(); err != nil {
return err
}
for i, v := range genDoc.Validators {
if v.Power == 0 {
return cmn.NewError("The genesis file cannot contain validators with no voting power: %v", v)
return errors.Errorf("The genesis file cannot contain validators with no voting power: %v", v)
}
if len(v.Address) > 0 && !bytes.Equal(v.PubKey.Address(), v.Address) {
return cmn.NewError("Incorrect address for validator %v in the genesis file, should be %v", v, v.PubKey.Address())
return errors.Errorf("Incorrect address for validator %v in the genesis file, should be %v", v, v.PubKey.Address())
}
if len(v.Address) == 0 {
genDoc.Validators[i].Address = v.PubKey.Address()
@@ -119,11 +119,11 @@ func GenesisDocFromJSON(jsonBlob []byte) (*GenesisDoc, error) {
func GenesisDocFromFile(genDocFile string) (*GenesisDoc, error) {
jsonBlob, err := ioutil.ReadFile(genDocFile)
if err != nil {
return nil, cmn.ErrorWrap(err, "Couldn't read GenesisDoc file")
return nil, errors.Wrap(err, "Couldn't read GenesisDoc file")
}
genDoc, err := GenesisDocFromJSON(jsonBlob)
if err != nil {
return nil, cmn.ErrorWrap(err, fmt.Sprintf("Error reading GenesisDoc at %v", genDocFile))
return nil, errors.Wrap(err, fmt.Sprintf("Error reading GenesisDoc at %v", genDocFile))
}
return genDoc, nil
}
+1 -1
View File
@@ -68,7 +68,7 @@ func TestGenesisGood(t *testing.T) {
genDoc.ConsensusParams.Block.MaxBytes = 0
genDocBytes, err = cdc.MarshalJSON(genDoc)
assert.NoError(t, err, "error marshalling genDoc")
genDoc, err = GenesisDocFromJSON(genDocBytes)
_, err = GenesisDocFromJSON(genDocBytes)
assert.Error(t, err, "expected error for genDoc json with block size of 0")
// Genesis doc from raw json
+9 -7
View File
@@ -1,6 +1,8 @@
package types
import (
"github.com/pkg/errors"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/tmhash"
cmn "github.com/tendermint/tendermint/libs/common"
@@ -95,38 +97,38 @@ func (params *ValidatorParams) IsValidPubkeyType(pubkeyType string) bool {
// allowed limits, and returns an error if they are not.
func (params *ConsensusParams) Validate() error {
if params.Block.MaxBytes <= 0 {
return cmn.NewError("Block.MaxBytes must be greater than 0. Got %d",
return errors.Errorf("Block.MaxBytes must be greater than 0. Got %d",
params.Block.MaxBytes)
}
if params.Block.MaxBytes > MaxBlockSizeBytes {
return cmn.NewError("Block.MaxBytes is too big. %d > %d",
return errors.Errorf("Block.MaxBytes is too big. %d > %d",
params.Block.MaxBytes, MaxBlockSizeBytes)
}
if params.Block.MaxGas < -1 {
return cmn.NewError("Block.MaxGas must be greater or equal to -1. Got %d",
return errors.Errorf("Block.MaxGas must be greater or equal to -1. Got %d",
params.Block.MaxGas)
}
if params.Block.TimeIotaMs <= 0 {
return cmn.NewError("Block.TimeIotaMs must be greater than 0. Got %v",
return errors.Errorf("Block.TimeIotaMs must be greater than 0. Got %v",
params.Block.TimeIotaMs)
}
if params.Evidence.MaxAge <= 0 {
return cmn.NewError("EvidenceParams.MaxAge must be greater than 0. Got %d",
return errors.Errorf("EvidenceParams.MaxAge must be greater than 0. Got %d",
params.Evidence.MaxAge)
}
if len(params.Validator.PubKeyTypes) == 0 {
return cmn.NewError("len(Validator.PubKeyTypes) must be greater than 0")
return errors.New("len(Validator.PubKeyTypes) must be greater than 0")
}
// Check if keyType is a known ABCIPubKeyType
for i := 0; i < len(params.Validator.PubKeyTypes); i++ {
keyType := params.Validator.PubKeyTypes[i]
if _, ok := ABCIPubKeyTypesToAminoNames[keyType]; !ok {
return cmn.NewError("params.Validator.PubKeyTypes[%d], %s, is an unknown pubkey type",
return errors.Errorf("params.Validator.PubKeyTypes[%d], %s, is an unknown pubkey type",
i, keyType)
}
}
+1
View File
@@ -12,6 +12,7 @@ import (
// PrivValidator defines the functionality of a local Tendermint validator
// that signs votes and proposals, and never double signs.
type PrivValidator interface {
// TODO: Extend the interface to return errors too. Issue: https://github.com/tendermint/tendermint/issues/3602
GetPubKey() crypto.PubKey
SignVote(chainID string, vote *Vote) error
+38 -2
View File
@@ -5,8 +5,7 @@ import (
)
func MakeCommit(blockID BlockID, height int64, round int,
voteSet *VoteSet,
validators []PrivValidator) (*Commit, error) {
voteSet *VoteSet, validators []PrivValidator) (*Commit, error) {
// all sign
for i := 0; i < len(validators); i++ {
@@ -37,3 +36,40 @@ func signAddVote(privVal PrivValidator, vote *Vote, voteSet *VoteSet) (signed bo
}
return voteSet.AddVote(vote)
}
func MakeVote(height int64, blockID BlockID, valSet *ValidatorSet, privVal PrivValidator, chainID string) (*Vote, error) {
addr := privVal.GetPubKey().Address()
idx, _ := valSet.GetByAddress(addr)
vote := &Vote{
ValidatorAddress: addr,
ValidatorIndex: idx,
Height: height,
Round: 0,
Timestamp: tmtime.Now(),
Type: PrecommitType,
BlockID: blockID,
}
if err := privVal.SignVote(chainID, vote); err != nil {
return nil, err
}
return vote, nil
}
// 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, lastCommit *Commit, evidence []Evidence) *Block {
block := &Block{
Header: Header{
Height: height,
NumTxs: int64(len(txs)),
},
Data: Data{
Txs: txs,
},
Evidence: EvidenceData{Evidence: evidence},
LastCommit: lastCommit,
}
block.fillHeader()
return block
}
+8 -6
View File
@@ -41,17 +41,19 @@ func (v *Validator) CompareProposerPriority(other *Validator) *Validator {
if v == nil {
return other
}
if v.ProposerPriority > other.ProposerPriority {
switch {
case v.ProposerPriority > other.ProposerPriority:
return v
} else if v.ProposerPriority < other.ProposerPriority {
case v.ProposerPriority < other.ProposerPriority:
return other
} else {
default:
result := bytes.Compare(v.Address, other.Address)
if result < 0 {
switch {
case result < 0:
return v
} else if result > 0 {
case result > 0:
return other
} else {
default:
panic("Cannot compare identical validators")
}
}
+8 -14
View File
@@ -2,15 +2,15 @@ package types
import (
"bytes"
"errors"
"fmt"
"math"
"math/big"
"sort"
"strings"
"github.com/pkg/errors"
"github.com/tendermint/tendermint/crypto/merkle"
cmn "github.com/tendermint/tendermint/libs/common"
)
// MaxTotalVotingPower - the maximum allowed total voting power.
@@ -121,7 +121,7 @@ func (vals *ValidatorSet) RescalePriorities(diffMax int64) {
ratio := (diff + diffMax - 1) / diffMax
if diff > diffMax {
for _, val := range vals.Validators {
val.ProposerPriority = val.ProposerPriority / ratio
val.ProposerPriority /= ratio
}
}
}
@@ -525,7 +525,7 @@ func (vals *ValidatorSet) applyRemovals(deletes []*Validator) {
// The 'allowDeletes' flag is set to false by NewValidatorSet() and to true by UpdateWithChangeSet().
func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes bool) error {
if len(changes) <= 0 {
if len(changes) == 0 {
return nil
}
@@ -626,9 +626,10 @@ func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height i
if blockID.Equals(precommit.BlockID) {
talliedVotingPower += val.VotingPower
}
// else {
// It's OK that the BlockID doesn't match. We include stray
// precommits to measure validator availability.
// }
}
if talliedVotingPower > vals.TotalVotingPower()*2/3 {
@@ -642,15 +643,8 @@ func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height i
// IsErrTooMuchChange
func IsErrTooMuchChange(err error) bool {
switch err_ := err.(type) {
case cmn.Error:
_, ok := err_.Data().(errTooMuchChange)
return ok
case errTooMuchChange:
return true
default:
return false
}
_, ok := errors.Cause(err).(errTooMuchChange)
return ok
}
type errTooMuchChange struct {
+3 -2
View File
@@ -4,9 +4,10 @@ import (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
"github.com/tendermint/tendermint/crypto"
cmn "github.com/tendermint/tendermint/libs/common"
tst "github.com/tendermint/tendermint/libs/test"
tmtime "github.com/tendermint/tendermint/types/time"
)
@@ -490,7 +491,7 @@ func TestMakeCommit(t *testing.T) {
}
// MakeCommit should fail.
tst.AssertPanics(t, "Doesn't have +2/3 majority", func() { voteSet.MakeCommit() })
assert.Panics(t, func() { voteSet.MakeCommit() }, "Doesn't have +2/3 majority")
// 7th voted for some other block.
{
+1
View File
@@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"