tests/quorum: add general consensus test

This commit is contained in:
Miya Chen 2017-09-06 11:32:22 +08:00
parent b6522e3db0
commit 035bc07c0a
1 changed files with 186 additions and 181 deletions

View File

@ -17,13 +17,20 @@
package functional
import (
"context"
"errors"
"fmt"
"math/big"
"sync"
"github.com/getamis/istanbul-tools/tests"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/getamis/istanbul-tools/container"
"github.com/getamis/istanbul-tools/genesis"
"github.com/getamis/istanbul-tools/tests"
)
var _ = Describe("QFS-01: General consensus", func() {
@ -49,67 +56,65 @@ var _ = Describe("QFS-01: General consensus", func() {
constellationNetwork.Finalize()
})
// FIt("QFS-01-01, QFS-01-02: Blockchain initialization and run", func() {
// fmt.Printf("validators:%v\n", blockchain.Validators())
// errc := make(chan error, len(blockchain.Validators()))
// valSet := make(map[common.Address]bool, numberOfValidators)
// for _, geth := range blockchain.Validators() {
// valSet[geth.Address()] = true
// }
// for _, geth := range blockchain.Validators() {
// go func(geth container.Ethereum) {
// // 1. Verify genesis block
// c := geth.NewClient()
// header, err := c.HeaderByNumber(context.Background(), big.NewInt(0))
// if err != nil {
// errc <- err
// return
// }
It("QFS-01-01, QFS-01-02: Blockchain initialization and run", func() {
errc := make(chan error, len(blockchain.Validators()))
valSet := make(map[common.Address]bool, numberOfValidators)
for _, geth := range blockchain.Validators() {
valSet[geth.Address()] = true
}
for _, geth := range blockchain.Validators() {
go func(geth container.Ethereum) {
// 1. Verify genesis block
c := geth.NewClient()
header, err := c.HeaderByNumber(context.Background(), big.NewInt(0))
if err != nil {
errc <- err
return
}
// if header.GasLimit.Int64() != genesis.InitGasLimit {
// errStr := fmt.Sprintf("Invalid genesis gas limit. want:%v, got:%v", genesis.InitGasLimit, header.GasLimit.Int64())
// errc <- errors.New(errStr)
// return
// }
if header.GasLimit.Int64() != genesis.InitGasLimit {
errStr := fmt.Sprintf("Invalid genesis gas limit. want:%v, got:%v", genesis.InitGasLimit, header.GasLimit.Int64())
errc <- errors.New(errStr)
return
}
// if header.Difficulty.Int64() != genesis.InitDifficulty {
// errStr := fmt.Sprintf("Invalid genesis difficulty. want:%v, got:%v", genesis.InitDifficulty, header.Difficulty.Int64())
// errc <- errors.New(errStr)
// return
// }
if header.Difficulty.Int64() != genesis.InitDifficulty {
errStr := fmt.Sprintf("Invalid genesis difficulty. want:%v, got:%v", genesis.InitDifficulty, header.Difficulty.Int64())
errc <- errors.New(errStr)
return
}
// if header.MixDigest != types.IstanbulDigest {
// errStr := fmt.Sprintf("Invalid block mixhash. want:%v, got:%v", types.IstanbulDigest, header.MixDigest)
// errc <- errors.New(errStr)
// return
if header.MixDigest != types.IstanbulDigest {
errStr := fmt.Sprintf("Invalid block mixhash. want:%v, got:%v", types.IstanbulDigest, header.MixDigest)
errc <- errors.New(errStr)
return
// }
}
// // 2. Check validator set
// istClient := geth.NewIstanbulClient()
// vals, err := istClient.GetValidators(context.Background(), big.NewInt(0))
// if err != nil {
// errc <- err
// return
// }
// 2. Check validator set
istClient := geth.NewIstanbulClient()
vals, err := istClient.GetValidators(context.Background(), big.NewInt(0))
if err != nil {
errc <- err
return
}
// for _, val := range vals {
// if _, ok := valSet[val]; !ok {
// errc <- errors.New("Invalid validator address.")
// return
// }
// }
for _, val := range vals {
if _, ok := valSet[val]; !ok {
errc <- errors.New("Invalid validator address.")
return
}
}
// errc <- nil
// }(geth)
// }
errc <- nil
}(geth)
}
// for i := 0; i < len(blockchain.Validators()); i++ {
// err := <-errc
// Expect(err).To(BeNil())
// }
// })
for i := 0; i < len(blockchain.Validators()); i++ {
err := <-errc
Expect(err).To(BeNil())
}
})
It("QFS-01-03: Peer connection", func(done Done) {
expectedPeerCount := len(blockchain.Validators()) - 1
@ -121,141 +126,141 @@ var _ = Describe("QFS-01: General consensus", func() {
close(done)
}, 20)
// It("TFS-01-04: Consensus progress", func(done Done) {
// const (
// targetBlockHeight = 10
// maxBlockPeriod = 3
// )
It("QFS-01-04: Consensus progress", func(done Done) {
const (
targetBlockHeight = 10
maxBlockPeriod = 3
)
// By("Wait for consensus progress", func() {
// tests.WaitFor(blockchain.Validators(), func(geth container.Ethereum, wg *sync.WaitGroup) {
// Expect(geth.WaitForBlockHeight(targetBlockHeight)).To(BeNil())
// wg.Done()
// })
// })
By("Wait for consensus progress", func() {
tests.WaitFor(blockchain.Validators(), func(geth container.Ethereum, wg *sync.WaitGroup) {
Expect(geth.WaitForBlockHeight(targetBlockHeight)).To(BeNil())
wg.Done()
})
})
// By("Check the block period should less than 3 seconds", func() {
// errc := make(chan error, len(blockchain.Validators()))
// for _, geth := range blockchain.Validators() {
// go func(geth container.Ethereum) {
// c := geth.NewClient()
// lastBlockTime := int64(0)
// // The reason to verify block period from block#2 is that
// // the block period from block#1 to block#2 might take long time due to
// // encounter several round changes at the beginning of the consensus progress.
// for i := 2; i <= targetBlockHeight; i++ {
// header, err := c.HeaderByNumber(context.Background(), big.NewInt(int64(i)))
// if err != nil {
// errc <- err
// return
// }
// if lastBlockTime != 0 {
// diff := header.Time.Int64() - lastBlockTime
// if diff > maxBlockPeriod {
// errStr := fmt.Sprintf("Invaild block(%v) period, want:%v, got:%v", header.Number.Int64(), maxBlockPeriod, diff)
// errc <- errors.New(errStr)
// return
// }
// }
// lastBlockTime = header.Time.Int64()
// }
// errc <- nil
// }(geth)
// }
By("Check the block period should less than 3 seconds", func() {
errc := make(chan error, len(blockchain.Validators()))
for _, geth := range blockchain.Validators() {
go func(geth container.Ethereum) {
c := geth.NewClient()
lastBlockTime := int64(0)
// The reason to verify block period from block#2 is that
// the block period from block#1 to block#2 might take long time due to
// encounter several round changes at the beginning of the consensus progress.
for i := 2; i <= targetBlockHeight; i++ {
header, err := c.HeaderByNumber(context.Background(), big.NewInt(int64(i)))
if err != nil {
errc <- err
return
}
if lastBlockTime != 0 {
diff := header.Time.Int64() - lastBlockTime
if diff > maxBlockPeriod {
errStr := fmt.Sprintf("Invaild block(%v) period, want:%v, got:%v", header.Number.Int64(), maxBlockPeriod, diff)
errc <- errors.New(errStr)
return
}
}
lastBlockTime = header.Time.Int64()
}
errc <- nil
}(geth)
}
// for i := 0; i < len(blockchain.Validators()); i++ {
// err := <-errc
// Expect(err).To(BeNil())
// }
// })
// close(done)
// }, 60)
for i := 0; i < len(blockchain.Validators()); i++ {
err := <-errc
Expect(err).To(BeNil())
}
})
close(done)
}, 60)
// It("TFS-01-05: Round robin proposer selection", func(done Done) {
// var (
// timesOfBeProposer = 3
// targetBlockHeight = timesOfBeProposer * numberOfValidators
// emptyProposer = common.Address{}
// )
It("QFS-01-05: Round robin proposer selection", func(done Done) {
var (
timesOfBeProposer = 3
targetBlockHeight = timesOfBeProposer * numberOfValidators
emptyProposer = common.Address{}
)
// By("Wait for consensus progress", func() {
// tests.WaitFor(blockchain.Validators(), func(geth container.Ethereum, wg *sync.WaitGroup) {
// Expect(geth.WaitForBlockHeight(targetBlockHeight)).To(BeNil())
// wg.Done()
// })
// })
By("Wait for consensus progress", func() {
tests.WaitFor(blockchain.Validators(), func(geth container.Ethereum, wg *sync.WaitGroup) {
Expect(geth.WaitForBlockHeight(targetBlockHeight)).To(BeNil())
wg.Done()
})
})
// By("Block proposer selection should follow round-robin policy", func() {
// errc := make(chan error, len(blockchain.Validators()))
// for _, geth := range blockchain.Validators() {
// go func(geth container.Ethereum) {
// c := geth.NewClient()
// istClient := geth.NewIstanbulClient()
By("Block proposer selection should follow round-robin policy", func() {
errc := make(chan error, len(blockchain.Validators()))
for _, geth := range blockchain.Validators() {
go func(geth container.Ethereum) {
c := geth.NewClient()
istClient := geth.NewIstanbulClient()
// // get initial validator set
// vals, err := istClient.GetValidators(context.Background(), big.NewInt(0))
// if err != nil {
// errc <- err
// return
// }
// get initial validator set
vals, err := istClient.GetValidators(context.Background(), big.NewInt(0))
if err != nil {
errc <- err
return
}
// lastProposerIdx := -1
// counts := make(map[common.Address]int, numberOfValidators)
// // initial count map
// for _, addr := range vals {
// counts[addr] = 0
// }
// for i := 1; i <= targetBlockHeight; i++ {
// header, err := c.HeaderByNumber(context.Background(), big.NewInt(int64(i)))
// if err != nil {
// errc <- err
// return
// }
lastProposerIdx := -1
counts := make(map[common.Address]int, numberOfValidators)
// initial count map
for _, addr := range vals {
counts[addr] = 0
}
for i := 1; i <= targetBlockHeight; i++ {
header, err := c.HeaderByNumber(context.Background(), big.NewInt(int64(i)))
if err != nil {
errc <- err
return
}
// p := container.GetProposer(header)
// if p == emptyProposer {
// errStr := fmt.Sprintf("Empty block(%v) proposer", header.Number.Int64())
// errc <- errors.New(errStr)
// return
// }
// // count the times to be the proposer
// if count, ok := counts[p]; ok {
// counts[p] = count + 1
// }
// // check if the proposer is valid
// if lastProposerIdx == -1 {
// for i, val := range vals {
// if p == val {
// lastProposerIdx = i
// break
// }
// }
// } else {
// proposerIdx := (lastProposerIdx + 1) % len(vals)
// if p != vals[proposerIdx] {
// errStr := fmt.Sprintf("Invaild block(%v) proposer, want:%v, got:%v", header.Number.Int64(), vals[proposerIdx], p)
// errc <- errors.New(errStr)
// return
// }
// lastProposerIdx = proposerIdx
// }
// }
// // check times to be proposer
// for _, count := range counts {
// if count != timesOfBeProposer {
// errc <- errors.New("Wrong times to be proposer.")
// return
// }
// }
// errc <- nil
// }(geth)
// }
p := container.GetProposer(header)
if p == emptyProposer {
errStr := fmt.Sprintf("Empty block(%v) proposer", header.Number.Int64())
errc <- errors.New(errStr)
return
}
// count the times to be the proposer
if count, ok := counts[p]; ok {
counts[p] = count + 1
}
// check if the proposer is valid
if lastProposerIdx == -1 {
for i, val := range vals {
if p == val {
lastProposerIdx = i
break
}
}
} else {
proposerIdx := (lastProposerIdx + 1) % len(vals)
if p != vals[proposerIdx] {
errStr := fmt.Sprintf("Invaild block(%v) proposer, want:%v, got:%v", header.Number.Int64(), vals[proposerIdx], p)
errc <- errors.New(errStr)
return
}
lastProposerIdx = proposerIdx
}
}
// check times to be proposer
for _, count := range counts {
if count != timesOfBeProposer {
errc <- errors.New("Wrong times to be proposer.")
return
}
}
errc <- nil
}(geth)
}
// for i := 0; i < len(blockchain.Validators()); i++ {
// err := <-errc
// Expect(err).To(BeNil())
// }
// })
// close(done)
// }, 120)
for i := 0; i < len(blockchain.Validators()); i++ {
err := <-errc
Expect(err).To(BeNil())
}
})
close(done)
}, 120)
})