From 035bc07c0ace30b92005bc93a3898b422fc43310 Mon Sep 17 00:00:00 2001 From: Miya Chen Date: Wed, 6 Sep 2017 11:32:22 +0800 Subject: [PATCH] tests/quorum: add general consensus test --- .../functional/general_consensus_test.go | 367 +++++++++--------- 1 file changed, 186 insertions(+), 181 deletions(-) diff --git a/tests/quorum/functional/general_consensus_test.go b/tests/quorum/functional/general_consensus_test.go index 99e6e446..43b6dc27 100644 --- a/tests/quorum/functional/general_consensus_test.go +++ b/tests/quorum/functional/general_consensus_test.go @@ -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) })