From 1defba5c7c49301013333e7cae69950250a2abef Mon Sep 17 00:00:00 2001 From: Marko Vukolic Date: Tue, 13 Dec 2016 21:41:14 +0100 Subject: [PATCH] sbft: amplify view-change from abdicating primary Towards FAB-474, we amplify the view-change when the primary of the current view sends a view change. In this case there is nothing to wait for and we proceed to the next view. Included a test that was failing (falling under FAB-474) but passes now. Change-Id: Ib5bb5ae827329aa7934c09cacfd6b6474475935c Signed-off-by: Marko Vukolic --- orderer/sbft/simplebft/simplebft_test.go | 58 ++++++++++++++++++++++++ orderer/sbft/simplebft/viewchange.go | 7 +++ 2 files changed, 65 insertions(+) diff --git a/orderer/sbft/simplebft/simplebft_test.go b/orderer/sbft/simplebft/simplebft_test.go index fba08f83f36..0f24e3c5767 100644 --- a/orderer/sbft/simplebft/simplebft_test.go +++ b/orderer/sbft/simplebft/simplebft_test.go @@ -531,6 +531,64 @@ func TestRestart(t *testing.T) { } } +func TestAbdicatingPrimary(t *testing.T) { + N := uint64(4) + sys := newTestSystem(N) + var repls []*SBFT + var adapters []*testSystemAdapter + for i := uint64(0); i < N; i++ { + a := sys.NewAdapter(i) + s, err := New(i, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, a) + if err != nil { + t.Fatal(err) + } + repls = append(repls, s) + adapters = append(adapters, a) + } + + phase := 1 + // Dropping all phase 1 msgs except requests and viewchange to 0 + // (preprepare to primary 0 is automatically delivered) + sys.filterFn = func(e testElem) (testElem, bool) { + if phase == 1 { + if msg, ok := e.ev.(*testMsgEvent); ok { + if c := msg.msg.GetRequest(); c != nil { + return e, true + } + if c := msg.msg.GetViewChange(); c != nil && msg.dst == 0 { + return e, true + } + return e, false + } + return e, true + } + return e, true + } + + connectAll(sys) + + r1 := []byte{1, 2, 3} + repls[0].Request(r1) + sys.Run() + + phase = 2 + + testLog.Notice("TEST: restarting connections from 0") + for _, a := range adapters { + if a.id != 0 { + a.receiver.Connection(0) + adapters[0].receiver.Connection(a.id) + } + } + + sys.Run() + for _, a := range adapters { + if len(a.batches) != 1 { + t.Fatalf("expected execution of 1 batch, %d got %v", a.id, a.batches) + } + } +} + func TestRestartAfterPrepare(t *testing.T) { N := uint64(4) sys := newTestSystem(N) diff --git a/orderer/sbft/simplebft/viewchange.go b/orderer/sbft/simplebft/viewchange.go index 0b9fffe213c..47751249036 100644 --- a/orderer/sbft/simplebft/viewchange.go +++ b/orderer/sbft/simplebft/viewchange.go @@ -84,6 +84,13 @@ func (s *SBFT) handleViewChange(svc *Signed, src uint64) { s.replicaState[src].signedViewchange = svc min := vc.View + + //amplify current primary abdication + if s.view == min-1 && s.primaryID() == src { + s.sendViewChange() + return + } + quorum := 0 for _, state := range s.replicaState { if state.viewchange != nil {