Skip to content

Commit 21d471b

Browse files
author
Marko Vukolic
committed
streamline sbft new-view and commit handling
streamlining and refactoring code. Change-Id: Ib32a66ce9345ebfa0050bdf08aa12ba6b8ed7ba4 Signed-off-by: Marko Vukolic <[email protected]>
1 parent ccb94c5 commit 21d471b

File tree

7 files changed

+52
-118
lines changed

7 files changed

+52
-118
lines changed

orderer/sbft/simplebft/commit.go

+15-4
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,17 @@ package simplebft
1919
import "reflect"
2020

2121
func (s *SBFT) maybeSendCommit() {
22-
if s.cur.sentCommit || len(s.cur.prep) < s.noFaultyQuorum()-1 {
22+
if s.cur.prepared || len(s.cur.prep) < s.noFaultyQuorum()-1 {
2323
return
2424
}
2525
s.sendCommit()
2626
s.processBacklog()
2727
}
2828

2929
func (s *SBFT) sendCommit() {
30-
s.cur.sentCommit = true
30+
s.cur.prepared = true
3131
c := s.cur.subject
32-
s.sys.Persist("commit", &c)
32+
s.sys.Persist(prepared, &c)
3333
s.broadcast(&Msg{&Msg_Commit{&c}})
3434
}
3535

@@ -50,5 +50,16 @@ func (s *SBFT) handleCommit(c *Subject, src uint64) {
5050
}
5151
s.cur.commit[src] = c
5252
s.cancelViewChangeTimer()
53-
s.maybeExecute()
53+
54+
//maybe mark as comitted
55+
if s.cur.committed || len(s.cur.commit) < s.noFaultyQuorum() {
56+
return
57+
}
58+
s.cur.committed = true
59+
log.Noticef("replica %d: executing %v %x", s.id, s.cur.subject.Seq, s.cur.subject.Digest)
60+
61+
s.sys.Persist(committed, &s.cur.subject)
62+
63+
s.sendCheckpoint()
64+
s.processBacklog()
5465
}

orderer/sbft/simplebft/connection.go

+3-26
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ func (s *SBFT) Connection(replica uint64) {
5555
} else {
5656
s.sys.Send(&Msg{&Msg_Prepare{&s.cur.subject}}, replica)
5757
}
58-
if s.cur.sentCommit {
58+
if s.cur.prepared {
5959
s.sys.Send(&Msg{&Msg_Commit{&s.cur.subject}}, replica)
6060
}
61-
if s.cur.executed {
61+
if s.cur.committed {
6262
s.sys.Send(&Msg{&Msg_Checkpoint{s.makeCheckpoint()}}, replica)
6363
}
6464
}
@@ -78,32 +78,9 @@ func (s *SBFT) handleHello(h *Hello, src uint64) {
7878
s.deliverBatch(h.Batch)
7979
}
8080

81-
if h.NewView != nil && s.view <= h.NewView.View {
82-
if s.primaryIDView(h.NewView.View) != src {
83-
log.Warningf("replica %d: invalid hello with new view from non-primary %d", s.id, src)
84-
return
85-
}
86-
87-
vcs, err := s.checkNewViewSignatures(h.NewView)
88-
if err != nil {
89-
log.Warningf("replica %d: invalid hello new view from %d: %s", s.id, src, err)
90-
return
91-
}
92-
93-
_, _, ok := s.makeXset(vcs)
94-
if !ok {
95-
log.Warningf("replica %d: invalid hello new view xset from %d", s.id, src)
96-
return
97-
}
98-
99-
s.view = h.NewView.View
100-
s.activeView = true
101-
102-
s.maybeDeliverUsingXset(h.NewView)
103-
}
81+
s.handleNewView(h.NewView, src)
10482

10583
s.replicaState[src].hello = h
106-
10784
s.discardBacklog(src)
10885
s.processBacklog()
10986
}

orderer/sbft/simplebft/execute.go

-30
This file was deleted.

orderer/sbft/simplebft/newview.go

+15-41
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ func (s *SBFT) checkNewViewSignatures(nv *NewView) ([]*ViewChange, error) {
8686
}
8787

8888
func (s *SBFT) handleNewView(nv *NewView, src uint64) {
89+
if nv == nil {
90+
return
91+
}
92+
8993
if nv.View < s.view {
9094
log.Debugf("replica %d: discarding old new view from %d for %d, we are in %d", s.id, src, nv.View, s.view)
9195
return
@@ -108,7 +112,7 @@ func (s *SBFT) handleNewView(nv *NewView, src uint64) {
108112
return
109113
}
110114

111-
xset, _, ok := s.makeXset(vcs)
115+
xset, prevBatch, ok := s.makeXset(vcs)
112116

113117
if !ok || !reflect.DeepEqual(nv.Xset, xset) {
114118
log.Warningf("replica %d: invalid new view from %d: xset incorrect: %v, %v", s.id, src, nv.Xset, xset)
@@ -139,36 +143,26 @@ func (s *SBFT) handleNewView(nv *NewView, src uint64) {
139143
}
140144
}
141145

142-
s.replicaState[s.primaryIDView(nv.View)].newview = nv
143146
s.view = nv.View
144-
s.activeView = false
145-
146-
s.processNewView()
147-
}
148-
149-
func (s *SBFT) processNewView() {
150-
if s.activeView {
151-
return
152-
}
147+
s.discardBacklog(s.primaryID())
153148

154-
nv := s.replicaState[s.primaryIDView(s.view)].newview
155-
if nv == nil || nv.View != s.view {
156-
return
149+
// maybe deliver using xset
150+
if s.sys.LastBatch().DecodeHeader().Seq < prevBatch.DecodeHeader().Seq {
151+
if prevBatch.DecodeHeader().Seq == s.cur.subject.Seq.Seq {
152+
// we just received a signature set for a request which we preprepared, but never delivered.
153+
prevBatch.Payloads = s.cur.preprep.Batch.Payloads
154+
}
155+
s.deliverBatch(prevBatch)
157156
}
158157

158+
// after a new-view message, prepare to accept new requests.
159159
s.activeView = true
160-
s.discardBacklog(s.primaryID())
161-
162-
s.maybeDeliverUsingXset(nv)
163-
164-
// By now we cannot be waiting for any more outstanding
165-
// messages. after a new-view message, by definition all
166-
// activity has acquiesced. Prepare to accept a new request.
167160
s.cur.checkpointDone = true
168161
s.cur.subject.Seq.Seq = 0
169162

170163
log.Infof("replica %d now active in view %d; primary: %v", s.id, s.view, s.isPrimary())
171164

165+
//process pre-prepare if piggybacked to new-view
172166
if nv.Batch != nil {
173167
pp := &Preprepare{
174168
Seq: &SeqView{Seq: nv.Batch.DecodeHeader().Seq, View: s.view},
@@ -184,23 +178,3 @@ func (s *SBFT) processNewView() {
184178

185179
s.processBacklog()
186180
}
187-
188-
func (s *SBFT) maybeDeliverUsingXset(nv *NewView) {
189-
// TODO we could cache vcs in replicaState
190-
vcs, err := s.checkNewViewSignatures(nv)
191-
if err != nil {
192-
panic(err)
193-
}
194-
195-
_, prevBatch, ok := s.makeXset(vcs)
196-
if !ok {
197-
panic("invalid newview")
198-
}
199-
if s.sys.LastBatch().DecodeHeader().Seq < prevBatch.DecodeHeader().Seq {
200-
if prevBatch.DecodeHeader().Seq == s.cur.subject.Seq.Seq {
201-
// we just received a signature set for a request which we preprepared, but never delivered.
202-
prevBatch.Payloads = s.cur.preprep.Batch.Payloads
203-
}
204-
s.deliverBatch(prevBatch)
205-
}
206-
}

orderer/sbft/simplebft/preprepare.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func (s *SBFT) sendPreprepare(batch []*Request) {
3636
Batch: s.makeBatch(seq.Seq, lasthash, data),
3737
}
3838

39-
s.sys.Persist("preprepare", m)
39+
s.sys.Persist(preprepared, m)
4040
s.broadcast(&Msg{&Msg_Preprepare{m}})
4141
s.handleCheckedPreprepare(m)
4242
}
@@ -83,7 +83,7 @@ func (s *SBFT) acceptPreprepare(pp *Preprepare) {
8383
sub := Subject{Seq: pp.Seq, Digest: pp.Batch.Hash()}
8484

8585
log.Infof("replica %d: accepting preprepare for %v, %x", s.id, sub.Seq, sub.Digest)
86-
s.sys.Persist("preprepare", pp)
86+
s.sys.Persist(preprepared, pp)
8787

8888
s.cur = reqInfo{
8989
subject: sub,

orderer/sbft/simplebft/simplebft.go

+15-11
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ import (
2525
"github.com/op/go-logging"
2626
)
2727

28+
const preprepared string = "preprepared"
29+
const prepared string = "prepared"
30+
const committed string = "committed"
31+
const viewchange string = "viewchange"
32+
2833
// Receiver defines the API that is exposed by SBFT to the system.
2934
type Receiver interface {
3035
Receive(msg *Msg, src uint64)
@@ -75,9 +80,9 @@ type reqInfo struct {
7580
preprep *Preprepare
7681
prep map[uint64]*Subject
7782
commit map[uint64]*Subject
78-
sentCommit bool
79-
executed bool
8083
checkpoint map[uint64]*Checkpoint
84+
prepared bool
85+
committed bool
8186
checkpointDone bool
8287
}
8388

@@ -86,7 +91,6 @@ type replicaInfo struct {
8691
hello *Hello
8792
signedViewchange *Signed
8893
viewchange *ViewChange
89-
newview *NewView
9094
}
9195

9296
var log = logging.MustGetLogger("sbft")
@@ -113,14 +117,14 @@ func New(id uint64, config *Config, sys System) (*SBFT, error) {
113117

114118
s.view = 0
115119
s.cur.subject.Seq = &SeqView{}
116-
s.cur.sentCommit = true
117-
s.cur.executed = true
120+
s.cur.prepared = true
121+
s.cur.committed = true
118122
s.cur.checkpointDone = true
119123
s.cur.timeout = dummyCanceller{}
120124
s.activeView = true
121125

122126
svc := &Signed{}
123-
if s.sys.Restore("viewchange", svc) {
127+
if s.sys.Restore(viewchange, svc) {
124128
vc := &ViewChange{}
125129
err := proto.Unmarshal(svc.Data, vc)
126130
if err != nil {
@@ -132,20 +136,20 @@ func New(id uint64, config *Config, sys System) (*SBFT, error) {
132136
}
133137

134138
pp := &Preprepare{}
135-
if s.sys.Restore("preprepare", pp) && pp.Seq.View >= s.view {
139+
if s.sys.Restore(preprepared, pp) && pp.Seq.View >= s.view {
136140
s.view = pp.Seq.View
137141
s.activeView = true
138142
if pp.Seq.Seq > s.seq() {
139143
s.acceptPreprepare(pp)
140144
}
141145
}
142146
c := &Subject{}
143-
if s.sys.Restore("commit", c) && reflect.DeepEqual(c, &s.cur.subject) && c.Seq.View >= s.view {
144-
s.cur.sentCommit = true
147+
if s.sys.Restore(prepared, c) && reflect.DeepEqual(c, &s.cur.subject) && c.Seq.View >= s.view {
148+
s.cur.prepared = true
145149
}
146150
ex := &Subject{}
147-
if s.sys.Restore("execute", ex) && reflect.DeepEqual(c, &s.cur.subject) && ex.Seq.View >= s.view {
148-
s.cur.executed = true
151+
if s.sys.Restore(committed, ex) && reflect.DeepEqual(c, &s.cur.subject) && ex.Seq.View >= s.view {
152+
s.cur.committed = true
149153
}
150154

151155
s.cancelViewChangeTimer()

orderer/sbft/simplebft/viewchange.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func (s *SBFT) sendViewChange() {
3131
log.Noticef("replica %d: sending viewchange for view %d", s.id, s.view)
3232

3333
var q, p []*Subject
34-
if s.cur.sentCommit {
34+
if s.cur.prepared {
3535
p = append(p, &s.cur.subject)
3636
}
3737
if s.cur.preprep != nil {
@@ -51,10 +51,8 @@ func (s *SBFT) sendViewChange() {
5151
s.viewChangeTimer.Cancel()
5252
s.cur.timeout.Cancel()
5353

54-
s.sys.Persist("viewchange", svc)
54+
s.sys.Persist(viewchange, svc)
5555
s.broadcast(&Msg{&Msg_ViewChange{svc}})
56-
57-
s.processNewView()
5856
}
5957

6058
func (s *SBFT) cancelViewChangeTimer() {

0 commit comments

Comments
 (0)