Merge pull request #42 from getamis/test/byzantine-faulty-behavior-testing
test: TFS-05 add byzantine faulty tests
This commit is contained in:
commit
d4591be74d
|
@ -72,6 +72,44 @@ func NewDefaultBlockchain(numOfValidators int) (bc *blockchain) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewDefaultBlockchainWithFaulty(numOfNormal int, numOfFaulty int) (bc *blockchain) {
|
||||||
|
commonOpts := [...]Option{
|
||||||
|
DataDir("/data"),
|
||||||
|
WebSocket(),
|
||||||
|
WebSocketAddress("0.0.0.0"),
|
||||||
|
WebSocketAPI("admin,eth,net,web3,personal,miner,istanbul"),
|
||||||
|
WebSocketOrigin("*"),
|
||||||
|
NAT("any"),
|
||||||
|
NoDiscover(),
|
||||||
|
Etherbase("1a9afb711302c5f83b5902843d1c007a1a137632"),
|
||||||
|
Mine(),
|
||||||
|
Logging(false)}
|
||||||
|
normalOpts := make([]Option, len(commonOpts), len(commonOpts)+2)
|
||||||
|
copy(normalOpts, commonOpts[:])
|
||||||
|
normalOpts = append(normalOpts, ImageRepository("quay.io/amis/geth"), ImageTag("istanbul_develop"))
|
||||||
|
faultyOpts := make([]Option, len(commonOpts), len(commonOpts)+3)
|
||||||
|
copy(faultyOpts, commonOpts[:])
|
||||||
|
faultyOpts = append(faultyOpts, ImageRepository("quay.io/amis/geth_faulty"), ImageTag("latest"), FaultyMode(1))
|
||||||
|
|
||||||
|
// New env client
|
||||||
|
bc = &blockchain{}
|
||||||
|
var err error
|
||||||
|
bc.dockerClient, err = client.NewEnvClient()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Cannot connect to Docker daemon, err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
keys, addrs := generateKeys(numOfNormal + numOfFaulty)
|
||||||
|
bc.setupGenesis(addrs)
|
||||||
|
// Create normal validators
|
||||||
|
bc.opts = normalOpts
|
||||||
|
bc.setupValidators(keys[:numOfNormal], bc.opts...)
|
||||||
|
// Create faulty validators
|
||||||
|
bc.opts = faultyOpts
|
||||||
|
bc.setupValidators(keys[numOfNormal:], bc.opts...)
|
||||||
|
return bc
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
type blockchain struct {
|
type blockchain struct {
|
||||||
|
|
|
@ -74,6 +74,8 @@ type Ethereum interface {
|
||||||
WaitForPeersConnected(int) error
|
WaitForPeersConnected(int) error
|
||||||
WaitForBlocks(int) error
|
WaitForBlocks(int) error
|
||||||
WaitForBlockHeight(int) error
|
WaitForBlockHeight(int) error
|
||||||
|
// Want for block for no more than the given number during the given time duration
|
||||||
|
WaitForNoBlocks(int, time.Duration) error
|
||||||
|
|
||||||
AddPeer(string) error
|
AddPeer(string) error
|
||||||
}
|
}
|
||||||
|
@ -523,6 +525,37 @@ func (eth *ethereum) WaitForBlockHeight(num int) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (eth *ethereum) WaitForNoBlocks(num int, duration time.Duration) error {
|
||||||
|
var first *big.Int
|
||||||
|
|
||||||
|
client := eth.NewIstanbulClient()
|
||||||
|
if client == nil {
|
||||||
|
return errors.New("failed to retrieve client")
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout := time.After(duration)
|
||||||
|
tick := time.Tick(time.Millisecond * 500)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-timeout:
|
||||||
|
return nil
|
||||||
|
case <-tick:
|
||||||
|
n, err := client.BlockNumber(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if first == nil {
|
||||||
|
first = new(big.Int).Set(n)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Check if new blocks are getting generated
|
||||||
|
if new(big.Int).Sub(n, first).Int64() > int64(num) {
|
||||||
|
return errors.New("generated more blocks than expected")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (eth *ethereum) AddPeer(address string) error {
|
func (eth *ethereum) AddPeer(address string) error {
|
||||||
client := eth.NewIstanbulClient()
|
client := eth.NewIstanbulClient()
|
||||||
if client == nil {
|
if client == nil {
|
||||||
|
|
|
@ -238,3 +238,10 @@ func Verbosity(verbosity int) Option {
|
||||||
eth.flags = append(eth.flags, fmt.Sprintf("%d", verbosity))
|
eth.flags = append(eth.flags, fmt.Sprintf("%d", verbosity))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FaultyMode(mode int) Option {
|
||||||
|
return func(eth *ethereum) {
|
||||||
|
eth.flags = append(eth.flags, "--istanbul.faultymode")
|
||||||
|
eth.flags = append(eth.flags, fmt.Sprintf("%d", mode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
// Copyright 2017 AMIS Technologies
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
|
"github.com/getamis/istanbul-tools/container"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("TFS-05: Byzantine Faulty", func() {
|
||||||
|
|
||||||
|
Context("TFS-05-01: F faulty validators", func() {
|
||||||
|
const (
|
||||||
|
numberOfNormal = 3
|
||||||
|
numberOfFaulty = 1
|
||||||
|
)
|
||||||
|
var (
|
||||||
|
blockchain container.Blockchain
|
||||||
|
)
|
||||||
|
BeforeEach(func() {
|
||||||
|
blockchain = container.NewDefaultBlockchainWithFaulty(numberOfNormal, numberOfFaulty)
|
||||||
|
Expect(blockchain.Start(true)).To(BeNil())
|
||||||
|
})
|
||||||
|
|
||||||
|
AfterEach(func() {
|
||||||
|
Expect(blockchain.Stop(false)).To(BeNil())
|
||||||
|
blockchain.Finalize()
|
||||||
|
})
|
||||||
|
|
||||||
|
It("Should generate blocks", func(done Done) {
|
||||||
|
|
||||||
|
By("Wait for p2p connection", func() {
|
||||||
|
waitFor(blockchain.Validators(), func(geth container.Ethereum, wg *sync.WaitGroup) {
|
||||||
|
Expect(geth.WaitForPeersConnected(numberOfNormal + numberOfFaulty - 1)).To(BeNil())
|
||||||
|
wg.Done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
By("Wait for blocks", func() {
|
||||||
|
const targetBlockHeight = 3
|
||||||
|
waitFor(blockchain.Validators()[:1], func(geth container.Ethereum, wg *sync.WaitGroup) {
|
||||||
|
Expect(geth.WaitForBlocks(targetBlockHeight)).To(BeNil())
|
||||||
|
wg.Done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
close(done)
|
||||||
|
}, 60)
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("TFS-05-01: F+1 faulty validators", func() {
|
||||||
|
const (
|
||||||
|
numberOfNormal = 2
|
||||||
|
numberOfFaulty = 2
|
||||||
|
)
|
||||||
|
var (
|
||||||
|
blockchain container.Blockchain
|
||||||
|
)
|
||||||
|
BeforeEach(func() {
|
||||||
|
blockchain = container.NewDefaultBlockchainWithFaulty(numberOfNormal, numberOfFaulty)
|
||||||
|
Expect(blockchain.Start(true)).To(BeNil())
|
||||||
|
})
|
||||||
|
|
||||||
|
AfterEach(func() {
|
||||||
|
Expect(blockchain.Stop(false)).To(BeNil())
|
||||||
|
blockchain.Finalize()
|
||||||
|
})
|
||||||
|
|
||||||
|
It("Should not generate blocks", func(done Done) {
|
||||||
|
By("Wait for p2p connection", func() {
|
||||||
|
waitFor(blockchain.Validators(), func(geth container.Ethereum, wg *sync.WaitGroup) {
|
||||||
|
Expect(geth.WaitForPeersConnected(numberOfNormal + numberOfFaulty - 1)).To(BeNil())
|
||||||
|
wg.Done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
By("Wait for blocks", func() {
|
||||||
|
// Only check normal validators
|
||||||
|
waitFor(blockchain.Validators()[:2], func(geth container.Ethereum, wg *sync.WaitGroup) {
|
||||||
|
Expect(geth.WaitForNoBlocks(0, time.Second*30)).To(BeNil())
|
||||||
|
wg.Done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
close(done)
|
||||||
|
}, 60)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
Loading…
Reference in New Issue