@@ -35,6 +35,8 @@ type Client struct {
3535 currentTipChan chan Tip
3636 wantFirstBlock bool
3737 firstBlockChan chan common.Point
38+ wantIntersectPoint bool
39+ intersectPointChan chan common.Point
3840 onceStop sync.Once
3941}
4042
@@ -58,6 +60,7 @@ func NewClient(protoOptions protocol.ProtocolOptions, cfg *Config) *Client {
5860 readyForNextBlockChan : make (chan bool ),
5961 currentTipChan : make (chan Tip ),
6062 firstBlockChan : make (chan common.Point ),
63+ intersectPointChan : make (chan common.Point ),
6164 }
6265 // Update state map with timeouts
6366 stateMap := StateMap .Copy ()
@@ -92,6 +95,7 @@ func NewClient(protoOptions protocol.ProtocolOptions, cfg *Config) *Client {
9295 close (c .readyForNextBlockChan )
9396 close (c .currentTipChan )
9497 close (c .firstBlockChan )
98+ close (c .intersectPointChan )
9599 }()
96100 return c
97101}
@@ -150,26 +154,46 @@ func (c *Client) GetCurrentTip() (*Tip, error) {
150154}
151155
152156// GetAvailableBlockRange returns the start and end of the range of available blocks given the provided intersect
153- // point(s).
157+ // point(s). Empty start/end points will be returned if there are no additional blocks available.
154158func (c * Client ) GetAvailableBlockRange (
155159 intersectPoints []common.Point ,
156160) (common.Point , common.Point , error ) {
157161 c .busyMutex .Lock ()
158162 defer c .busyMutex .Unlock ()
159163 var start , end common.Point
164+ // Find our chain intersection
165+ c .wantCurrentTip = true
166+ c .wantIntersectPoint = true
160167 msgFindIntersect := NewMsgFindIntersect (intersectPoints )
161168 if err := c .SendMessage (msgFindIntersect ); err != nil {
162169 return start , end , err
163170 }
164- select {
165- case err := <- c .intersectResultChan :
166- if err != nil {
167- return start , end , err
171+ gotIntersectResult := false
172+ for {
173+ select {
174+ case tip := <- c .currentTipChan :
175+ end = tip .Point
176+ c .wantCurrentTip = false
177+ case point := <- c .intersectPointChan :
178+ start = point
179+ c .wantIntersectPoint = false
180+ case err := <- c .intersectResultChan :
181+ if err != nil {
182+ return start , end , err
183+ }
184+ gotIntersectResult = true
185+ }
186+ if ! c .wantIntersectPoint && ! c .wantCurrentTip && gotIntersectResult {
187+ break
168188 }
169189 }
190+ // If we're already at the chain tip, return an empty range
191+ if start .Slot >= end .Slot {
192+ return common.Point {}, common.Point {}, nil
193+ }
194+ // Request the next block to get the first block after the intersect point. This should result in a rollback
170195 c .wantCurrentTip = true
171196 c .wantFirstBlock = true
172- // Request the next block. This should result in a rollback
173197 msgRequestNext := NewMsgRequestNext ()
174198 if err := c .SendMessage (msgRequestNext ); err != nil {
175199 return start , end , err
@@ -193,6 +217,10 @@ func (c *Client) GetAvailableBlockRange(
193217 break
194218 }
195219 }
220+ // If we're already at the chain tip, return an empty range
221+ if start .Slot >= end .Slot {
222+ return common.Point {}, common.Point {}, nil
223+ }
196224 return start , end , nil
197225}
198226
@@ -356,11 +384,14 @@ func (c *Client) handleRollBackward(msg protocol.Message) error {
356384 return nil
357385}
358386
359- func (c * Client ) handleIntersectFound (msgGeneric protocol.Message ) error {
387+ func (c * Client ) handleIntersectFound (msg protocol.Message ) error {
388+ msgIntersectFound := msg .(* MsgIntersectFound )
360389 if c .wantCurrentTip {
361- msgIntersectFound := msgGeneric .(* MsgIntersectFound )
362390 c .currentTipChan <- msgIntersectFound .Tip
363391 }
392+ if c .wantIntersectPoint {
393+ c .intersectPointChan <- msgIntersectFound .Point
394+ }
364395 c .intersectResultChan <- nil
365396 return nil
366397}
0 commit comments