Skip to content

Commit 6f81835

Browse files
author
Marko Vukolic
committed
fix sbft backlog processing
sbft backlog needs to be processed on every phase transition. Otherwise, messages put in the backlog may be as good as lost, in case, e.g., a pre-prepare is received after corresponding prepare/commit/checkpoint msgs. This is demonstrated by the new test TestMsgReordering (which would so far fail) in simplebft_test.go. Change-Id: I4b38a922e5d565c8e7a92a66f3e125fd30e8715f Signed-off-by: Marko Vukolic <[email protected]>
1 parent 0c5736c commit 6f81835

File tree

4 files changed

+57
-2
lines changed

4 files changed

+57
-2
lines changed

orderer/sbft/simplebft/commit.go

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ func (s *SBFT) maybeSendCommit() {
2323
return
2424
}
2525
s.sendCommit()
26+
s.processBacklog()
2627
}
2728

2829
func (s *SBFT) sendCommit() {

orderer/sbft/simplebft/execute.go

+1
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@ func (s *SBFT) maybeExecute() {
2626
s.sys.Persist("execute", &s.cur.subject)
2727

2828
s.sendCheckpoint()
29+
s.processBacklog()
2930
}

orderer/sbft/simplebft/preprepare.go

+1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ func (s *SBFT) handleCheckedPreprepare(pp *Preprepare) {
9999
s.acceptPreprepare(pp)
100100
if !s.isPrimary() {
101101
s.sendPrepare()
102+
s.processBacklog()
102103
}
103104

104105
s.maybeSendCommit()

orderer/sbft/simplebft/simplebft_test.go

+54-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ var testLog = logging.MustGetLogger("test")
2929

3030
func init() {
3131
logging.SetLevel(logging.NOTICE, "")
32-
// logging.SetLevel(logging.DEBUG, "test")
33-
// logging.SetLevel(logging.DEBUG, "sbft")
32+
//logging.SetLevel(logging.DEBUG, "test")
33+
//logging.SetLevel(logging.DEBUG, "sbft")
3434
}
3535

3636
func connectAll(sys *testSystem) {
@@ -259,6 +259,58 @@ func TestViewChange(t *testing.T) {
259259
}
260260
}
261261

262+
func TestMsgReordering(t *testing.T) {
263+
N := uint64(4)
264+
sys := newTestSystem(N)
265+
var repls []*SBFT
266+
var adapters []*testSystemAdapter
267+
for i := uint64(0); i < N; i++ {
268+
a := sys.NewAdapter(i)
269+
s, err := New(i, &Config{N: N, F: 1, BatchDurationNsec: 2000000000, BatchSizeBytes: 1, RequestTimeoutNsec: 20000000000}, a)
270+
if err != nil {
271+
t.Fatal(err)
272+
}
273+
repls = append(repls, s)
274+
adapters = append(adapters, a)
275+
}
276+
277+
var preprep *testMsgEvent
278+
279+
// forcing pre-prepare from primary 0 to reach replica 1 after some delay
280+
// effectivelly delivering pre-prepare instead of checkpoint
281+
sys.filterFn = func(e testElem) (testElem, bool) {
282+
if msg, ok := e.ev.(*testMsgEvent); ok {
283+
if msg.src == 0 && msg.dst == 1 {
284+
c := msg.msg.GetPreprepare()
285+
if c != nil && c.Seq.View == 0 {
286+
preprep = msg //memorizing pre-prepare
287+
return e, false // but dropping it
288+
}
289+
d := msg.msg.GetCheckpoint()
290+
if d != nil {
291+
msg.msg = &Msg{&Msg_Preprepare{preprep.msg.GetPreprepare()}}
292+
return e, true //and delivering it
293+
}
294+
return e, false //droping other msgs from 0 to 1
295+
}
296+
}
297+
return e, true
298+
}
299+
300+
connectAll(sys)
301+
r1 := []byte{1, 2, 3}
302+
repls[0].Request(r1)
303+
sys.Run()
304+
for _, a := range adapters {
305+
if len(a.batches) != 1 {
306+
t.Fatal("expected execution of 1 batch")
307+
}
308+
if !reflect.DeepEqual([][]byte{r1}, a.batches[0].Payloads) {
309+
t.Error("wrong request executed (1)")
310+
}
311+
}
312+
}
313+
262314
func TestViewChangeWithRetransmission(t *testing.T) {
263315
N := uint64(4)
264316
sys := newTestSystem(N)

0 commit comments

Comments
 (0)