Skip to content

Commit 44d5564

Browse files
author
Marko Vukolic
committedDec 13, 2016
fix non monotonic views in sbft
sbft was not persisting view change messages which led to replicas returning to previous views. Previously failing test included. Change-Id: Ie9c9afd372c9a80f36da67fdbcb696336b9586c6 Signed-off-by: Marko Vukolic <mvu@zurich.ibm.com>
1 parent fe16a6d commit 44d5564

File tree

3 files changed

+54
-7
lines changed

3 files changed

+54
-7
lines changed
 

‎orderer/sbft/simplebft/simplebft.go

+17-7
Original file line numberDiff line numberDiff line change
@@ -117,27 +117,37 @@ func New(id uint64, config *Config, sys System) (*SBFT, error) {
117117
s.cur.executed = true
118118
s.cur.checkpointDone = true
119119
s.cur.timeout = dummyCanceller{}
120+
s.activeView = true
121+
122+
svc := &Signed{}
123+
if s.sys.Restore("viewchange", svc) {
124+
vc := &ViewChange{}
125+
err := proto.Unmarshal(svc.Data, vc)
126+
if err != nil {
127+
return nil, err
128+
}
129+
s.view = vc.View
130+
s.replicaState[s.id].signedViewchange = svc
131+
s.activeView = false
132+
}
120133

121134
pp := &Preprepare{}
122-
if s.sys.Restore("preprepare", pp) {
135+
if s.sys.Restore("preprepare", pp) && pp.Seq.View >= s.view {
123136
s.view = pp.Seq.View
137+
s.activeView = true
124138
if pp.Seq.Seq > s.seq() {
125139
s.acceptPreprepare(pp)
126140
}
127141
}
128142
c := &Subject{}
129-
if s.sys.Restore("commit", c) && reflect.DeepEqual(c, &s.cur.subject) {
143+
if s.sys.Restore("commit", c) && reflect.DeepEqual(c, &s.cur.subject) && c.Seq.View >= s.view {
130144
s.cur.sentCommit = true
131145
}
132146
ex := &Subject{}
133-
if s.sys.Restore("execute", ex) && reflect.DeepEqual(c, &s.cur.subject) {
147+
if s.sys.Restore("execute", ex) && reflect.DeepEqual(c, &s.cur.subject) && ex.Seq.View >= s.view {
134148
s.cur.executed = true
135149
}
136150

137-
if s.seq() == 0 {
138-
s.activeView = true
139-
}
140-
141151
s.cancelViewChangeTimer()
142152
return s, nil
143153
}

‎orderer/sbft/simplebft/simplebft_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,41 @@ func TestN1(t *testing.T) {
166166
}
167167
}
168168

169+
func TestMonotonicViews(t *testing.T) {
170+
N := uint64(4)
171+
sys := newTestSystem(N)
172+
var repls []*SBFT
173+
var adapters []*testSystemAdapter
174+
for i := uint64(0); i < N; i++ {
175+
a := sys.NewAdapter(i)
176+
s, err := New(i, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, a)
177+
if err != nil {
178+
t.Fatal(err)
179+
}
180+
repls = append(repls, s)
181+
adapters = append(adapters, a)
182+
}
183+
184+
repls[0].sendViewChange()
185+
sys.Run()
186+
187+
view := repls[0].view
188+
testLog.Notice("TEST: Replica 0 is in view ", view)
189+
testLog.Notice("TEST: restarting replica 0")
190+
repls[0], _ = New(0, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 10, RequestTimeoutNsec: 20000000000}, adapters[0])
191+
for _, a := range adapters {
192+
if a.id != 0 {
193+
a.receiver.Connection(0)
194+
adapters[0].receiver.Connection(a.id)
195+
}
196+
}
197+
sys.Run()
198+
199+
if repls[0].view != view {
200+
t.Fatalf("Replica 0 must be in view %d, but is in view %d", view, repls[0].view)
201+
}
202+
}
203+
169204
func TestByzPrimary(t *testing.T) {
170205
N := uint64(4)
171206
sys := newTestSystem(N)

‎orderer/sbft/simplebft/viewchange.go

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ func (s *SBFT) sendViewChange() {
5050
svc := s.sign(vc)
5151
s.viewChangeTimer.Cancel()
5252
s.cur.timeout.Cancel()
53+
54+
s.sys.Persist("viewchange", svc)
5355
s.broadcast(&Msg{&Msg_ViewChange{svc}})
5456

5557
s.processNewView()

0 commit comments

Comments
 (0)
Please sign in to comment.