From c163c8608c22f2554b365aa34f7f88f111aed7ea Mon Sep 17 00:00:00 2001 From: Simon Schubert Date: Wed, 16 Nov 2016 13:56:10 +0100 Subject: [PATCH] sbft: send view change message on reconnect Change-Id: Iaff9f6deb1ebb727e5d262d2efb9f9bfd5252944 Signed-off-by: Simon Schubert --- orderer/sbft/simplebft/connection.go | 5 ++ orderer/sbft/simplebft/simplebft_test.go | 59 ++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/orderer/sbft/simplebft/connection.go b/orderer/sbft/simplebft/connection.go index 140a3dc7302..d4ecadbf6d0 100644 --- a/orderer/sbft/simplebft/connection.go +++ b/orderer/sbft/simplebft/connection.go @@ -29,6 +29,11 @@ func (s *SBFT) Connection(replica uint64) { } s.sys.Send(&Msg{&Msg_Hello{hello}}, replica) + svc := s.replicaState[s.id].signedViewchange + if svc != nil { + s.sys.Send(&Msg{&Msg_ViewChange{svc}}, replica) + } + // A reconnecting replica can play forward its blockchain to // the batch listed in the hello message. However, the // currently in-flight batch will not be reflected in the diff --git a/orderer/sbft/simplebft/simplebft_test.go b/orderer/sbft/simplebft/simplebft_test.go index e583ed83fc3..44754380b2c 100644 --- a/orderer/sbft/simplebft/simplebft_test.go +++ b/orderer/sbft/simplebft/simplebft_test.go @@ -885,3 +885,62 @@ func TestViewChangeTimer(t *testing.T) { } } } + +func TestResendViewChange(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 := make(map[uint64]int) + + // prevent first view change from being delivered + sys.filterFn = func(e testElem) (testElem, bool) { + if msg, ok := e.ev.(*testMsgEvent); ok { + if msg.dst == msg.src { + return e, true + } else if phase[msg.src] == 0 && msg.msg.GetViewChange() != nil { + return e, false + } else if msg.msg.GetHello() != nil { + phase[msg.src] = 1 + } + } + + return e, true + } + + for _, r := range repls { + r.sendViewChange() + } + sys.Run() + + connectAll(sys) + r1 := []byte{1, 2, 3} + repls[0].Request(r1) + sys.Run() + r2 := []byte{3, 1, 2} + r3 := []byte{3, 5, 2} + repls[1].Request(r2) + repls[1].Request(r3) + sys.Run() + for _, a := range adapters { + if len(a.batches) != 3 { + t.Fatal("expected execution of 2 batches") + } + if !reflect.DeepEqual([][]byte{r1}, a.batches[1].Payloads) { + t.Error("wrong request executed (1)") + } + if !reflect.DeepEqual([][]byte{r2, r3}, a.batches[2].Payloads) { + t.Error("wrong request executed (2)") + } + } +}