From b096651e108d5d6fd729ca29649bf29c9ebc3a2d Mon Sep 17 00:00:00 2001 From: Anton Kalyaev Date: Wed, 4 Jan 2017 00:32:39 +0400 Subject: [PATCH 1/4] fix glide error: unable to export dependencies to vendor directory ``` [ERROR] Unable to export dependencies to vendor directory: remove /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/golang.org/x/sys/unix: directory not empty ``` --- Makefile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 6a3b2381f..8835722b8 100644 --- a/Makefile +++ b/Makefile @@ -12,19 +12,19 @@ NOVENDOR = go list github.com/tendermint/tendermint/... | grep -v /vendor/ install: get_deps go install github.com/tendermint/tendermint/cmd/tendermint -build: +build: go build -o build/tendermint github.com/tendermint/tendermint/cmd/tendermint -build_race: +build_race: go build -race -o build/tendermint github.com/tendermint/tendermint/cmd/tendermint test: build go test `${NOVENDOR}` - + test_race: build go test -race `${NOVENDOR}` -test_integrations: +test_integrations: bash ./test/test.sh test100: build @@ -48,6 +48,7 @@ get_deps: get_vendor_deps: go get github.com/Masterminds/glide + rm -rf vendor/ glide install update_deps: From a1fd312bb1031cb290cdaca689d52e504029e006 Mon Sep 17 00:00:00 2001 From: Anton Kalyaev Date: Wed, 4 Jan 2017 01:50:02 +0400 Subject: [PATCH 2/4] make progress asap on full precommit votes optional (Refs #348) --- config/tendermint/config.go | 2 ++ config/tendermint_test/config.go | 1 + consensus/reactor_test.go | 6 +++++ consensus/state.go | 41 +++++++++++++++++--------------- 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/config/tendermint/config.go b/config/tendermint/config.go index a48f801e9..2e8d90254 100644 --- a/config/tendermint/config.go +++ b/config/tendermint/config.go @@ -84,6 +84,8 @@ func GetConfig(rootDir string) cfg.Config { mapConfig.SetDefault("timeout_precommit", 1000) mapConfig.SetDefault("timeout_precommit_delta", 500) mapConfig.SetDefault("timeout_commit", 1000) + // make progress asap (no `timeout_commit`) on full precommit votes + mapConfig.SetDefault("skip_timeout_commit", false) mapConfig.SetDefault("mempool_recheck", true) mapConfig.SetDefault("mempool_recheck_empty", true) mapConfig.SetDefault("mempool_broadcast", true) diff --git a/config/tendermint_test/config.go b/config/tendermint_test/config.go index 28b1da805..2913546c5 100644 --- a/config/tendermint_test/config.go +++ b/config/tendermint_test/config.go @@ -98,6 +98,7 @@ func ResetConfig(localPath string) cfg.Config { mapConfig.SetDefault("timeout_precommit", 10) mapConfig.SetDefault("timeout_precommit_delta", 1) mapConfig.SetDefault("timeout_commit", 10) + mapConfig.SetDefault("skip_timeout_commit", false) mapConfig.SetDefault("mempool_recheck", true) mapConfig.SetDefault("mempool_recheck_empty", true) mapConfig.SetDefault("mempool_broadcast", true) diff --git a/consensus/reactor_test.go b/consensus/reactor_test.go index 995f4a387..d7fd3ba5d 100644 --- a/consensus/reactor_test.go +++ b/consensus/reactor_test.go @@ -149,6 +149,12 @@ func TestValidatorSetChanges(t *testing.T) { nPeers := 8 nVals := 4 css := randConsensusNetWithPeers(nVals, nPeers, "consensus_val_set_changes_test", newMockTickerFunc(true), newPersistentDummy) + + // otherwise, the test is failing with timeout error + for i := 0; i < nPeers; i++ { + css[i].timeoutParams.SkipCommit0 = true + } + reactors := make([]*ConsensusReactor, nPeers) eventChans := make([]chan interface{}, nPeers) for i := 0; i < nPeers; i++ { diff --git a/consensus/state.go b/consensus/state.go index 3020a214a..13125a5d3 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -24,15 +24,17 @@ import ( //----------------------------------------------------------------------------- // Timeout Parameters -// All in milliseconds +// TimeoutParams holds timeouts and deltas for each round step. +// All timeouts and deltas in milliseconds. type TimeoutParams struct { - Propose0 int - ProposeDelta int - Prevote0 int - PrevoteDelta int - Precommit0 int - PrecommitDelta int - Commit0 int + Propose0 int + ProposeDelta int + Prevote0 int + PrevoteDelta int + Precommit0 int + PrecommitDelta int + Commit0 int + SkipTimeoutCommit bool } // Wait this long for a proposal @@ -55,16 +57,17 @@ func (tp *TimeoutParams) Commit(t time.Time) time.Time { return t.Add(time.Duration(tp.Commit0) * time.Millisecond) } -// Initialize parameters from config +// InitTimeoutParamsFromConfig initializes parameters from config func InitTimeoutParamsFromConfig(config cfg.Config) *TimeoutParams { return &TimeoutParams{ - Propose0: config.GetInt("timeout_propose"), - ProposeDelta: config.GetInt("timeout_propose_delta"), - Prevote0: config.GetInt("timeout_prevote"), - PrevoteDelta: config.GetInt("timeout_prevote_delta"), - Precommit0: config.GetInt("timeout_precommit"), - PrecommitDelta: config.GetInt("timeout_precommit_delta"), - Commit0: config.GetInt("timeout_commit"), + Propose0: config.GetInt("timeout_propose"), + ProposeDelta: config.GetInt("timeout_propose_delta"), + Prevote0: config.GetInt("timeout_prevote"), + PrevoteDelta: config.GetInt("timeout_prevote_delta"), + Precommit0: config.GetInt("timeout_precommit"), + PrecommitDelta: config.GetInt("timeout_precommit_delta"), + Commit0: config.GetInt("timeout_commit"), + SkipTimeoutCommit: config.GetBool("skip_timeout_commit"), } } @@ -1388,8 +1391,8 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerKey string) (added bool, log.Info(Fmt("Added to lastPrecommits: %v", cs.LastCommit.StringShort())) types.FireEventVote(cs.evsw, types.EventDataVote{vote}) - if cs.LastCommit.HasAll() { - // if we have all the votes now, + // if we can skip timeoutCommit and have all the votes now, + if cs.timeoutParams.SkipTimeoutCommit && cs.LastCommit.HasAll() { // go straight to new round (skip timeout commit) // cs.scheduleTimeout(time.Duration(0), cs.Height, 0, RoundStepNewHeight) cs.enterNewRound(cs.Height, 0) @@ -1452,7 +1455,7 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerKey string) (added bool, cs.enterPrecommit(height, vote.Round) cs.enterCommit(height, vote.Round) - if precommits.HasAll() { + if cs.timeoutParams.SkipTimeoutCommit && cs.LastCommit.HasAll() { // if we have all the votes now, // go straight to new round (skip timeout commit) // cs.scheduleTimeout(time.Duration(0), cs.Height, 0, RoundStepNewHeight) From 3308ac7d8393c991914458bb30894f9f2e72a822 Mon Sep 17 00:00:00 2001 From: Anton Kalyaev Date: Thu, 5 Jan 2017 00:06:11 +0400 Subject: [PATCH 3/4] set skip_timeout_commit to true for tests For the tests its better to not use the timeout_commit, and to wait for all the votes, because otherwise we can end up with timing dependencies in the testing code which can lead to nondeterministic failures. That was part of the reason for this change originally. --- config/tendermint_test/config.go | 2 +- consensus/reactor_test.go | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/config/tendermint_test/config.go b/config/tendermint_test/config.go index 2913546c5..421c0017b 100644 --- a/config/tendermint_test/config.go +++ b/config/tendermint_test/config.go @@ -98,7 +98,7 @@ func ResetConfig(localPath string) cfg.Config { mapConfig.SetDefault("timeout_precommit", 10) mapConfig.SetDefault("timeout_precommit_delta", 1) mapConfig.SetDefault("timeout_commit", 10) - mapConfig.SetDefault("skip_timeout_commit", false) + mapConfig.SetDefault("skip_timeout_commit", true) mapConfig.SetDefault("mempool_recheck", true) mapConfig.SetDefault("mempool_recheck_empty", true) mapConfig.SetDefault("mempool_broadcast", true) diff --git a/consensus/reactor_test.go b/consensus/reactor_test.go index d7fd3ba5d..29391c290 100644 --- a/consensus/reactor_test.go +++ b/consensus/reactor_test.go @@ -150,11 +150,6 @@ func TestValidatorSetChanges(t *testing.T) { nVals := 4 css := randConsensusNetWithPeers(nVals, nPeers, "consensus_val_set_changes_test", newMockTickerFunc(true), newPersistentDummy) - // otherwise, the test is failing with timeout error - for i := 0; i < nPeers; i++ { - css[i].timeoutParams.SkipCommit0 = true - } - reactors := make([]*ConsensusReactor, nPeers) eventChans := make([]chan interface{}, nPeers) for i := 0; i < nPeers; i++ { From 535fc6cd63247f889116c81544e788c0dffd6659 Mon Sep 17 00:00:00 2001 From: Anton Kalyaev Date: Thu, 5 Jan 2017 00:26:31 +0400 Subject: [PATCH 4/4] test we can make blocks with skip_timeout_commit=false --- consensus/reactor_test.go | 43 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/consensus/reactor_test.go b/consensus/reactor_test.go index 29391c290..f2024fe81 100644 --- a/consensus/reactor_test.go +++ b/consensus/reactor_test.go @@ -262,6 +262,49 @@ func TestValidatorSetChanges(t *testing.T) { waitForAndValidateBlock(t, nPeers, activeVals, eventChans, css) } +// Check we can make blocks with skip_timeout_commit=false +func TestReactorWithTimeoutCommit(t *testing.T) { + N := 4 + css := randConsensusNet(N, "consensus_reactor_with_timeout_commit_test", newMockTickerFunc(false)) + + // override default SkipTimeoutCommit == true for tests + for i := 0; i < N; i++ { + css[i].timeoutParams.SkipTimeoutCommit = false + } + + reactors := make([]*ConsensusReactor, N-1) + eventChans := make([]chan interface{}, N-1) + for i := 0; i < N-1; i++ { + reactors[i] = NewConsensusReactor(css[i], true) // so we dont start the consensus states + + eventSwitch := events.NewEventSwitch() + _, err := eventSwitch.Start() + if err != nil { + t.Fatalf("Failed to start switch: %v", err) + } + + reactors[i].SetEventSwitch(eventSwitch) + eventChans[i] = subscribeToEvent(eventSwitch, "tester", types.EventStringNewBlock(), 1) + } + // make connected switches and start all reactors + p2p.MakeConnectedSwitches(N-1, func(i int, s *p2p.Switch) *p2p.Switch { + s.AddReactor("CONSENSUS", reactors[i]) + return s + }, p2p.Connect2Switches) + + // start the state machines + for i := 0; i < N-1; i++ { + s := reactors[i].conS.GetState() + reactors[i].SwitchToConsensus(s) + } + + // wait till everyone makes the first new block + timeoutWaitGroup(t, N-1, func(wg *sync.WaitGroup, j int) { + <-eventChans[j] + wg.Done() + }) +} + func waitForAndValidateBlock(t *testing.T, n int, activeVals map[string]struct{}, eventChans []chan interface{}, css []*ConsensusState, txs ...[]byte) { timeoutWaitGroup(t, n, func(wg *sync.WaitGroup, j int) { newBlockI := <-eventChans[j]