@@ -4,11 +4,15 @@ import (
44 "fmt"
55 "github.com/cloudstruct/go-cardano-ledger"
66 "github.com/cloudstruct/go-ouroboros-network/protocol"
7+ "sync"
78)
89
910type Client struct {
1011 * protocol.Protocol
11- config * Config
12+ config * Config
13+ busyMutex sync.Mutex
14+ intersectResultChan chan error
15+ readyForNextBlockChan chan bool
1216}
1317
1418func NewClient (protoOptions protocol.ProtocolOptions , cfg * Config ) * Client {
@@ -21,7 +25,9 @@ func NewClient(protoOptions protocol.ProtocolOptions, cfg *Config) *Client {
2125 msgFromCborFunc = NewMsgFromCborNtN
2226 }
2327 c := & Client {
24- config : cfg ,
28+ config : cfg ,
29+ intersectResultChan : make (chan error ),
30+ readyForNextBlockChan : make (chan bool ),
2531 }
2632 protoConfig := protocol.ProtocolConfig {
2733 Name : PROTOCOL_NAME ,
@@ -52,36 +58,73 @@ func (c *Client) messageHandler(msg protocol.Message, isResponse bool) error {
5258 err = c .handleIntersectFound (msg )
5359 case MESSAGE_TYPE_INTERSECT_NOT_FOUND :
5460 err = c .handleIntersectNotFound (msg )
55- case MESSAGE_TYPE_DONE :
56- err = c .handleDone ()
5761 default :
5862 err = fmt .Errorf ("%s: received unexpected message type %d" , PROTOCOL_NAME , msg .Type ())
5963 }
6064 return err
6165}
6266
63- func (c * Client ) RequestNext () error {
64- msg := NewMsgRequestNext ()
65- return c .SendMessage (msg )
67+ func (c * Client ) Stop () error {
68+ c .busyMutex .Lock ()
69+ defer c .busyMutex .Unlock ()
70+ msg := NewMsgDone ()
71+ if err := c .SendMessage (msg ); err != nil {
72+ return err
73+ }
74+ return nil
6675}
6776
68- func (c * Client ) FindIntersect (points []Point ) error {
69- msg := NewMsgFindIntersect (points )
70- return c .SendMessage (msg )
77+ func (c * Client ) Sync (intersectPoints []Point ) error {
78+ c .busyMutex .Lock ()
79+ defer c .busyMutex .Unlock ()
80+ msg := NewMsgFindIntersect (intersectPoints )
81+ if err := c .SendMessage (msg ); err != nil {
82+ return err
83+ }
84+ if err := <- c .intersectResultChan ; err != nil {
85+ return err
86+ }
87+ // Pipeline the initial block requests to speed things up a bit
88+ // Using a value higher than 10 seems to cause problems with NtN
89+ for i := 0 ; i < 10 ; i ++ {
90+ msg := NewMsgRequestNext ()
91+ if err := c .SendMessage (msg ); err != nil {
92+ return err
93+ }
94+ }
95+ go c .syncLoop ()
96+ return nil
7197}
7298
73- func (c * Client ) handleAwaitReply () error {
74- if c .config .AwaitReplyFunc == nil {
75- return fmt .Errorf ("received chain-sync AwaitReply message but no callback function is defined" )
99+ func (c * Client ) syncLoop () {
100+ for {
101+ // Wait for a block to be received
102+ <- c .readyForNextBlockChan
103+ c .busyMutex .Lock ()
104+ // Request the next block
105+ // In practice we already have multiple block requests pipelined
106+ // and this just adds another one to the pile
107+ msg := NewMsgRequestNext ()
108+ if err := c .SendMessage (msg ); err != nil {
109+ c .SendError (err )
110+ return
111+ }
112+ c .busyMutex .Unlock ()
76113 }
77- // Call the user callback function
78- return c .config .AwaitReplyFunc ()
114+ }
115+
116+ func (c * Client ) handleAwaitReply () error {
117+ return nil
79118}
80119
81120func (c * Client ) handleRollForward (msgGeneric protocol.Message ) error {
82121 if c .config .RollForwardFunc == nil {
83122 return fmt .Errorf ("received chain-sync RollForward message but no callback function is defined" )
84123 }
124+ // Signal that we're ready for the next block after we finish handling this one
125+ defer func () {
126+ c .readyForNextBlockChan <- true
127+ }()
85128 if c .Mode () == protocol .ProtocolModeNodeToNode {
86129 msg := msgGeneric .(* MsgRollForwardNtN )
87130 var blockHeader interface {}
@@ -112,15 +155,15 @@ func (c *Client) handleRollForward(msgGeneric protocol.Message) error {
112155 }
113156 }
114157 // Call the user callback function
115- return c .config .RollForwardFunc (blockType , blockHeader )
158+ return c .config .RollForwardFunc (blockType , blockHeader , msg . Tip )
116159 } else {
117160 msg := msgGeneric .(* MsgRollForwardNtC )
118161 blk , err := ledger .NewBlockFromCbor (msg .BlockType (), msg .BlockCbor ())
119162 if err != nil {
120163 return err
121164 }
122165 // Call the user callback function
123- return c .config .RollForwardFunc (msg .BlockType (), blk )
166+ return c .config .RollForwardFunc (msg .BlockType (), blk , msg . Tip )
124167 }
125168}
126169
@@ -134,27 +177,11 @@ func (c *Client) handleRollBackward(msgGeneric protocol.Message) error {
134177}
135178
136179func (c * Client ) handleIntersectFound (msgGeneric protocol.Message ) error {
137- if c .config .IntersectFoundFunc == nil {
138- return fmt .Errorf ("received chain-sync IntersectFound message but no callback function is defined" )
139- }
140- msg := msgGeneric .(* MsgIntersectFound )
141- // Call the user callback function
142- return c .config .IntersectFoundFunc (msg .Point , msg .Tip )
180+ c .intersectResultChan <- nil
181+ return nil
143182}
144183
145184func (c * Client ) handleIntersectNotFound (msgGeneric protocol.Message ) error {
146- if c .config .IntersectNotFoundFunc == nil {
147- return fmt .Errorf ("received chain-sync IntersectNotFound message but no callback function is defined" )
148- }
149- msg := msgGeneric .(* MsgIntersectNotFound )
150- // Call the user callback function
151- return c .config .IntersectNotFoundFunc (msg .Tip )
152- }
153-
154- func (c * Client ) handleDone () error {
155- if c .config .DoneFunc == nil {
156- return fmt .Errorf ("received chain-sync Done message but no callback function is defined" )
157- }
158- // Call the user callback function
159- return c .config .DoneFunc ()
185+ c .intersectResultChan <- IntersectNotFoundError {}
186+ return nil
160187}
0 commit comments