Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add tests for each validator type #189

Merged
merged 2 commits into from
Mar 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions consensus/aggregate_signature_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package consensus

import (
"crypto/ed25519"
"testing"

"github.com/tendermint/tendermint/crypto/bls"

"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/log"
)

func startConsensusAndMakeBlocks(t *testing.T, nPeers, nVals, nValsWithComposite int) []*State {
css, _, _, cleanup := consensusNetWithPeers(
nVals,
nPeers,
t.Name(),
newMockTickerFunc(true),
newPersistentKVStoreWithPath,
nValsWithComposite)

defer cleanup()
logger := log.TestingLogger()

reactors, blocksSubs, eventBuses := startConsensusNet(t, css, nPeers)
defer stopConsensusNet(logger, reactors, eventBuses)

// map of active validators
activeVals := make(map[string]struct{})
for i := 0; i < nVals; i++ {
pubKey, err := css[i].privValidator.GetPubKey()
require.NoError(t, err)
activeVals[string(pubKey.Address())] = struct{}{}
}

// wait till everyone makes block 1
timeoutWaitGroup(t, nPeers, func(j int) {
<-blocksSubs[j].Out()
}, css)

// wait till everyone makes block 2
waitForAndValidateBlock(t, nPeers, activeVals, blocksSubs, css)

return css
}

func TestAggregateSignature(t *testing.T) {
const (
nPeers = 4
nVals = 4
nValsWithComposite = 0
)
css := startConsensusAndMakeBlocks(t, nPeers, nVals, nValsWithComposite)
for _, state := range css {
block := state.blockStore.LoadBlock(2)

// validators are ed25519 only
for _, comsig := range block.LastCommit.Signatures {
require.EqualValues(t, ed25519.PrivateKeySize, len(comsig.Signature))
}
require.EqualValues(t, nVals, len(block.LastCommit.Signatures))
require.Nil(t, block.LastCommit.AggregatedSignature)
}
}

func TestAggregateSignatureWithComposite(t *testing.T) {
const (
nPeers = 4
nVals = 4
nValsWithComposite = 4
)
css := startConsensusAndMakeBlocks(t, nPeers, nVals, nValsWithComposite)

for _, state := range css {
block := state.blockStore.LoadBlock(2)
// validators are composite only
for _, comsig := range block.LastCommit.Signatures {
require.Nil(t, comsig.Signature)
}
require.EqualValues(t, nVals, len(block.LastCommit.Signatures))
require.EqualValues(t, bls.SignatureSize, len(block.LastCommit.AggregatedSignature))
}
}

func TestAggregateSignatureWithMix(t *testing.T) {
const (
nPeers = 4
nVals = 4
nValsWithComposite = 2
expectedCntNotNilSig = nVals - nValsWithComposite
)
css := startConsensusAndMakeBlocks(t, nPeers, nVals, nValsWithComposite)

for _, state := range css {
block := state.blockStore.LoadBlock(2)
// composite and ed25519 validators
cnt := 0
for _, comsig := range block.LastCommit.Signatures {
if comsig.Signature != nil {
cnt++
}
}
// count the unaggregated sig
require.EqualValues(t, expectedCntNotNilSig, cnt)
// count the aggregated sig
require.EqualValues(t, nValsWithComposite, len(block.LastCommit.Signatures)-cnt)
}
}
92 changes: 87 additions & 5 deletions consensus/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,28 @@ func randConsensusNet(nValidators int, testName string, tickerFunc func() Timeou
}
}

// nPeers = nValidators(ed25519 or composite) + nNotValidator
// (0 <= numOfComposite <= nValidators)
func consensusNetWithPeers(
nValidators,
nPeers int,
testName string,
tickerFunc func() TimeoutTicker,
appFunc func(string) abci.Application,
nValsWithComposite int,
) ([]*State, *types.GenesisDoc, *cfg.Config, cleanupFunc) {
genDoc, privVals := genesisDoc(nValidators, testMinPower, types.DefaultVoterParams(), nValsWithComposite)

css, peer0Config, configRootDirs := createPeersAndValidators(nValidators, nPeers, testName,
genDoc, privVals, tickerFunc, appFunc)

return css, genDoc, peer0Config, func() {
for _, dir := range configRootDirs {
os.RemoveAll(dir)
}
}
}

// nPeers = nValidators + nNotValidator
func randConsensusNetWithPeers(
nValidators,
Expand All @@ -777,6 +799,19 @@ func randConsensusNetWithPeers(
appFunc func(string) abci.Application,
) ([]*State, *types.GenesisDoc, *cfg.Config, cleanupFunc) {
genDoc, privVals := randGenesisDoc(nValidators, false, testMinPower, types.DefaultVoterParams())
css, peer0Config, configRootDirs := createPeersAndValidators(nValidators, nPeers, testName,
genDoc, privVals, tickerFunc, appFunc)

return css, genDoc, peer0Config, func() {
for _, dir := range configRootDirs {
os.RemoveAll(dir)
}
}
}

func createPeersAndValidators(nValidators, nPeers int, testName string,
genDoc *types.GenesisDoc, privVals []types.PrivValidator, tickerFunc func() TimeoutTicker,
appFunc func(string) abci.Application) ([]*State, *cfg.Config, []string) {
css := make([]*State, nPeers)
logger := consensusLogger()
var peer0Config *cfg.Config
Expand Down Expand Up @@ -819,11 +854,8 @@ func randConsensusNetWithPeers(
css[i].SetTimeoutTicker(tickerFunc())
css[i].SetLogger(logger.With("validator", i, "module", "consensus"))
}
return css, genDoc, peer0Config, func() {
for _, dir := range configRootDirs {
os.RemoveAll(dir)
}
}

return css, peer0Config, configRootDirs
}

func getSwitchIndex(switches []*p2p.Switch, peer p2p.Peer) int {
Expand All @@ -837,6 +869,41 @@ func getSwitchIndex(switches []*p2p.Switch, peer p2p.Peer) int {

//-------------------------------------------------------------------------------
// genesis
func genesisDoc(
numValidators int,
minPower int64,
voterParams *types.VoterParams,
nValsWithComposite int,
) (*types.GenesisDoc, []types.PrivValidator) {
validators := make([]types.GenesisValidator, numValidators)
privValidators := make([]types.PrivValidator, numValidators)
var val *types.Validator
var privVal types.PrivValidator
for i := 0; i < nValsWithComposite; i++ {
val, privVal = createTestValidator(minPower, types.PrivKeyComposite)
validators[i] = types.GenesisValidator{
PubKey: val.PubKey,
Power: val.StakingPower,
}
privValidators[i] = privVal
}
for i := nValsWithComposite; i < numValidators; i++ {
val, privVal = createTestValidator(minPower, types.PrivKeyEd25519)
validators[i] = types.GenesisValidator{
PubKey: val.PubKey,
Power: val.StakingPower,
}
privValidators[i] = privVal
}
sort.Sort(types.PrivValidatorsByAddress(privValidators))

return &types.GenesisDoc{
GenesisTime: tmtime.Now(),
ChainID: config.ChainID(),
Validators: validators,
VoterParams: voterParams,
}, privValidators
}

func randGenesisDoc(
numValidators int,
Expand Down Expand Up @@ -936,3 +1003,18 @@ func newPersistentKVStore() abci.Application {
func newPersistentKVStoreWithPath(dbDir string) abci.Application {
return kvstore.NewPersistentKVStoreApplication(dbDir)
}

//----------------------------------------
// Validator
func createTestValidator(minPower int64, keytype types.PrivKeyType) (*types.Validator, types.PrivValidator) {
privVal := types.NewMockPV(keytype)
stakingPower := minPower
stakingPower += 100

pubKey, err := privVal.GetPubKey()
if err != nil {
panic(fmt.Errorf("could not retrieve pubkey %w", err))
}
val := types.NewValidator(pubKey, stakingPower)
return val, privVal
}
20 changes: 20 additions & 0 deletions privval/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import (
"fmt"
"io/ioutil"
"os"
"reflect"
"testing"
"time"

"github.com/tendermint/tendermint/crypto/composite"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

Expand All @@ -17,6 +20,23 @@ import (
tmtime "github.com/tendermint/tendermint/types/time"
)

func TestGenFilePV(t *testing.T) {
tempKeyFile, err := ioutil.TempFile("", "priv_validator_key_")
require.Nil(t, err)
tempStateFile, err := ioutil.TempFile("", "priv_validator_state_")
require.Nil(t, err)

privValEd25519, err := GenFilePV(tempKeyFile.Name(), tempStateFile.Name(), PrivKeyTypeEd25519)
require.EqualValues(t, reflect.TypeOf(ed25519.PubKeyEd25519{}), reflect.TypeOf(privValEd25519.Key.PubKey))

privValComposite, err := GenFilePV(tempKeyFile.Name(), tempStateFile.Name(), PrivKeyTypeComposite)
require.EqualValues(t, reflect.TypeOf(composite.PubKeyComposite{}), reflect.TypeOf(privValComposite.Key.PubKey))

privValUndefinedPrivKeyType, err := GenFilePV(tempKeyFile.Name(), tempStateFile.Name(), "")
require.NotNil(t, err)
require.Nil(t, privValUndefinedPrivKeyType)
}

func TestGenLoadValidator(t *testing.T) {
assert := assert.New(t)

Expand Down