From 10be4468323460bdbcb0020961130404be3e65fa Mon Sep 17 00:00:00 2001 From: Edwin Date: Thu, 24 Aug 2017 17:46:26 +0800 Subject: [PATCH 1/3] tests: watch few block and see if the newly added validator has been picked as proposer at least once. --- container/ethereum.go | 41 ++++++++++++++++++++++++++++++++++++++++- container/utils.go | 12 ++++++++++++ tests/dynamic_test.go | 12 ++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/container/ethereum.go b/container/ethereum.go index 92a0fcc2..f2403d7f 100644 --- a/container/ethereum.go +++ b/container/ethereum.go @@ -37,11 +37,13 @@ import ( "github.com/docker/go-connections/nat" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/istanbul" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/getamis/istanbul-tools/cmd/istanbul/extradata" "github.com/getamis/istanbul-tools/genesis" "github.com/getamis/istanbul-tools/istclient" ) @@ -70,6 +72,7 @@ type Ethereum interface { NewIstanbulClient() *istclient.Client ConsensusMonitor(err chan<- error, quit chan struct{}) + WaitForProposed(expectedAddress common.Address, t time.Duration) error WaitForPeersConnected(int) error WaitForBlocks(int) error WaitForBlockHeight(int) error @@ -401,7 +404,7 @@ func (eth *ethereum) ConsensusMonitor(errCh chan<- error, quit chan struct{}) { log.Printf("Connection lost: %v", err) errCh <- err return - case <-timer.C: + case <-timer.C: // FIXME: this event may be missed if blockNumber == 0 { errCh <- ErrNoBlock } else { @@ -423,6 +426,42 @@ func (eth *ethereum) ConsensusMonitor(errCh chan<- error, quit chan struct{}) { } } +// TODO: refactor with ConsensusMonitor +func (eth *ethereum) WaitForProposed(expectedAddress common.Address, timeout time.Duration) error { + cli := eth.NewClient() + + subCh := make(chan *ethtypes.Header) + + sub, err := cli.SubscribeNewHead(context.Background(), subCh) + if err != nil { + return err + } + defer sub.Unsubscribe() + + timer := time.NewTimer(timeout) + for { + select { + case err := <-sub.Err(): + return err + case <-timer.C: // FIXME: this event may be missed + return errors.New("no result") + case head := <-subCh: + _, istanbulExtra, err := extradata.Decode(common.ToHex(head.Extra)) + if err != nil { + return err + } + addr, err := istanbul.GetSignatureAddress(sigHash(head).Bytes(), istanbulExtra.Seal) + if err != nil { + return err + } + + if addr.String() == expectedAddress.String() { + return nil + } + } + } +} + func (eth *ethereum) WaitForPeersConnected(expectedPeercount int) error { client := eth.NewIstanbulClient() if client == nil { diff --git a/container/utils.go b/container/utils.go index e8481827..5b073e38 100644 --- a/container/utils.go +++ b/container/utils.go @@ -24,7 +24,10 @@ import ( "path/filepath" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/crypto/sha3" + "github.com/ethereum/go-ethereum/rlp" uuid "github.com/satori/go.uuid" ) @@ -78,3 +81,12 @@ func saveNodeKey(key *ecdsa.PrivateKey, dataDir string) error { } return nil } + +func sigHash(header *types.Header) (hash common.Hash) { + hasher := sha3.NewKeccak256() + + // Clean seal is required for calculating proposer seal. + rlp.Encode(hasher, types.IstanbulFilteredHeader(header, false)) + hasher.Sum(hash[:0]) + return hash +} diff --git a/tests/dynamic_test.go b/tests/dynamic_test.go index e5e9142f..b3779613 100644 --- a/tests/dynamic_test.go +++ b/tests/dynamic_test.go @@ -72,6 +72,18 @@ var _ = Describe("Dynamic validators addition/removal testing", func() { } }) + It("TFS-02-02 New validators consensus participation", func() { + testValidator := 1 + + newValidators, err := blockchain.AddValidators(testValidator) + Expect(err).Should(BeNil()) + + waitFor(blockchain.Validators()[numberOfValidators:], func(eth container.Ethereum, wg *sync.WaitGroup) { + Expect(eth.WaitForProposed(newValidators[0].Address(), 100*time.Second)).Should(BeNil()) + wg.Done() + }) + }) + It("TFS-02-03 Remove validators", func() { numOfCandidates := 3 From 204376eab238b56aec0646edae656228d089507a Mon Sep 17 00:00:00 2001 From: Edwin Date: Thu, 24 Aug 2017 18:01:57 +0800 Subject: [PATCH 2/3] container: add getProposer function to utils --- container/ethereum.go | 13 +------------ container/utils.go | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/container/ethereum.go b/container/ethereum.go index f2403d7f..1f6a8ccb 100644 --- a/container/ethereum.go +++ b/container/ethereum.go @@ -37,13 +37,11 @@ import ( "github.com/docker/go-connections/nat" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/istanbul" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/p2p/discover" - "github.com/getamis/istanbul-tools/cmd/istanbul/extradata" "github.com/getamis/istanbul-tools/genesis" "github.com/getamis/istanbul-tools/istclient" ) @@ -446,16 +444,7 @@ func (eth *ethereum) WaitForProposed(expectedAddress common.Address, timeout tim case <-timer.C: // FIXME: this event may be missed return errors.New("no result") case head := <-subCh: - _, istanbulExtra, err := extradata.Decode(common.ToHex(head.Extra)) - if err != nil { - return err - } - addr, err := istanbul.GetSignatureAddress(sigHash(head).Bytes(), istanbulExtra.Seal) - if err != nil { - return err - } - - if addr.String() == expectedAddress.String() { + if getProposer(head).String() == expectedAddress.String() { return nil } } diff --git a/container/utils.go b/container/utils.go index 5b073e38..86a33e5b 100644 --- a/container/utils.go +++ b/container/utils.go @@ -24,10 +24,12 @@ import ( "path/filepath" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/istanbul" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/sha3" "github.com/ethereum/go-ethereum/rlp" + "github.com/getamis/istanbul-tools/cmd/istanbul/extradata" uuid "github.com/satori/go.uuid" ) @@ -90,3 +92,20 @@ func sigHash(header *types.Header) (hash common.Hash) { hasher.Sum(hash[:0]) return hash } + +func getProposer(header *types.Header) common.Address { + if header == nil { + return common.Address{} + } + + _, istanbulExtra, err := extradata.Decode(common.ToHex(header.Extra)) + if err != nil { + return common.Address{} + } + + addr, err := istanbul.GetSignatureAddress(sigHash(header).Bytes(), istanbulExtra.Seal) + if err != nil { + return common.Address{} + } + return addr +} From 331353534c74bab95dcf0d0bb9c26fc5071c913b Mon Sep 17 00:00:00 2001 From: Edwin Date: Fri, 25 Aug 2017 10:29:45 +0800 Subject: [PATCH 3/3] fix pr comments --- container/ethereum.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/ethereum.go b/container/ethereum.go index 1f6a8ccb..594fef1a 100644 --- a/container/ethereum.go +++ b/container/ethereum.go @@ -444,7 +444,7 @@ func (eth *ethereum) WaitForProposed(expectedAddress common.Address, timeout tim case <-timer.C: // FIXME: this event may be missed return errors.New("no result") case head := <-subCh: - if getProposer(head).String() == expectedAddress.String() { + if getProposer(head) == expectedAddress { return nil } }