@@ -10,7 +10,7 @@ import (
10
10
"github.com/NethermindEth/juno/core/felt"
11
11
"github.com/NethermindEth/juno/feed"
12
12
"github.com/NethermindEth/juno/jsonrpc"
13
- "github.com/NethermindEth/juno/sync"
13
+ junoSync "github.com/NethermindEth/juno/sync"
14
14
"github.com/sourcegraph/conc"
15
15
)
16
16
@@ -67,24 +67,46 @@ func (h *Handler) SubscribeEvents(ctx context.Context, fromAddr *felt.Felt, keys
67
67
h .mu .Unlock ()
68
68
69
69
headerSub := h .newHeads .Subscribe ()
70
- reorgSub := h .reorgs .Subscribe () // as per the spec, reorgs are also sent in the events subscription
70
+ reorgSub := h .reorgs .Subscribe () // as per the spec, reorgs are also sent in the events subscription#
71
+ pendingSub := h .pendingBlock .Subscribe ()
71
72
sub .wg .Go (func () {
72
73
defer func () {
73
74
h .unsubscribe (sub , id )
74
75
headerSub .Unsubscribe ()
75
76
reorgSub .Unsubscribe ()
77
+ pendingSub .Unsubscribe ()
76
78
}()
77
79
78
- // The specification doesn't enforce ordering of events therefore events from new blocks can be sent before
80
+ // The specification doesn't enforce ordering of events, therefore, events from new blocks can be sent before
79
81
// old blocks.
80
82
var wg conc.WaitGroup
81
83
wg .Go (func () {
84
+ // Stores the transaction hash of the event
85
+ eventsPreviouslySent := make (map [felt.Felt ]struct {})
86
+
82
87
for {
83
88
select {
84
89
case <- subscriptionCtx .Done ():
85
90
return
86
91
case header := <- headerSub .Recv ():
87
- h .processEvents (subscriptionCtx , w , id , header .Number , header .Number , fromAddr , keys )
92
+ // During syncing the events from the new head still need to be sent as there is no pending block.
93
+ // However, it is not easy to tell when the node is syncing.
94
+ // To solve this issue, we can send the events regardless, and if the node is done syncing, then the
95
+ // latest header events would have been sent when the pending block was updated. Hence,
96
+ // trying to resend the event should be of no consequences and the map can be safely emptied.
97
+ h .processEvents (subscriptionCtx , w , id , header .Number , header .Number , fromAddr , keys , eventsPreviouslySent )
98
+
99
+ b , err := h .bcReader .BlockByNumber (header .Number )
100
+ if err != nil {
101
+ h .log .Warnw ("Error retrieving block" , "block number" , header .Number , "err" , err )
102
+ return
103
+ }
104
+
105
+ for _ , t := range b .Transactions {
106
+ delete (eventsPreviouslySent , * t .Hash ())
107
+ }
108
+ case pending := <- pendingSub .Recv ():
109
+ h .processEvents (subscriptionCtx , w , id , pending .Number , pending .Number , fromAddr , keys , eventsPreviouslySent )
88
110
}
89
111
}
90
112
})
@@ -94,7 +116,7 @@ func (h *Handler) SubscribeEvents(ctx context.Context, fromAddr *felt.Felt, keys
94
116
})
95
117
96
118
wg .Go (func () {
97
- h .processEvents (subscriptionCtx , w , id , requestedHeader .Number , headHeader .Number , fromAddr , keys )
119
+ h .processEvents (subscriptionCtx , w , id , requestedHeader .Number , headHeader .Number , fromAddr , keys , nil )
98
120
})
99
121
100
122
wg .Wait ()
@@ -252,7 +274,9 @@ func (h *Handler) SubscribeTransactionStatus(ctx context.Context, txHash felt.Fe
252
274
return & SubscriptionID {ID : id }, nil
253
275
}
254
276
255
- func (h * Handler ) processEvents (ctx context.Context , w jsonrpc.Conn , id , from , to uint64 , fromAddr * felt.Felt , keys [][]felt.Felt ) {
277
+ func (h * Handler ) processEvents (ctx context.Context , w jsonrpc.Conn , id , from , to uint64 , fromAddr * felt.Felt ,
278
+ keys [][]felt.Felt , eventsPreviouslySent map [felt.Felt ]struct {},
279
+ ) {
256
280
filter , err := h .bcReader .EventFilter (fromAddr , keys )
257
281
if err != nil {
258
282
h .log .Warnw ("Error creating event filter" , "err" , err )
@@ -272,7 +296,7 @@ func (h *Handler) processEvents(ctx context.Context, w jsonrpc.Conn, id, from, t
272
296
return
273
297
}
274
298
275
- err = sendEvents (ctx , w , filteredEvents , id )
299
+ err = sendEvents (ctx , w , filteredEvents , eventsPreviouslySent , id )
276
300
if err != nil {
277
301
h .log .Warnw ("Error sending events" , "err" , err )
278
302
return
@@ -285,20 +309,29 @@ func (h *Handler) processEvents(ctx context.Context, w jsonrpc.Conn, id, from, t
285
309
return
286
310
}
287
311
288
- err = sendEvents (ctx , w , filteredEvents , id )
312
+ err = sendEvents (ctx , w , filteredEvents , eventsPreviouslySent , id )
289
313
if err != nil {
290
314
h .log .Warnw ("Error sending events" , "err" , err )
291
315
return
292
316
}
293
317
}
294
318
}
295
319
296
- func sendEvents (ctx context.Context , w jsonrpc.Conn , events []* blockchain.FilteredEvent , id uint64 ) error {
320
+ func sendEvents (ctx context.Context , w jsonrpc.Conn , events []* blockchain.FilteredEvent ,
321
+ eventsPreviouslySent map [felt.Felt ]struct {}, id uint64 ,
322
+ ) error {
297
323
for _ , event := range events {
298
324
select {
299
325
case <- ctx .Done ():
300
326
return ctx .Err ()
301
327
default :
328
+ if eventsPreviouslySent != nil {
329
+ if _ , exists := eventsPreviouslySent [* event .TransactionHash ]; exists {
330
+ continue
331
+ }
332
+ eventsPreviouslySent [* event .TransactionHash ] = struct {}{}
333
+ }
334
+
302
335
emittedEvent := & EmittedEvent {
303
336
BlockNumber : & event .BlockNumber , // This always be filled as subscribeEvents cannot be called on pending block
304
337
BlockHash : event .BlockHash ,
@@ -604,7 +637,7 @@ func (h *Handler) sendHeader(w jsonrpc.Conn, header *core.Header, id uint64) err
604
637
return err
605
638
}
606
639
607
- func (h * Handler ) processReorgs (ctx context.Context , reorgSub * feed.Subscription [* sync .ReorgBlockRange ], w jsonrpc.Conn , id uint64 ) {
640
+ func (h * Handler ) processReorgs (ctx context.Context , reorgSub * feed.Subscription [* junoSync .ReorgBlockRange ], w jsonrpc.Conn , id uint64 ) {
608
641
for {
609
642
select {
610
643
case <- ctx .Done ():
@@ -625,7 +658,7 @@ type ReorgEvent struct {
625
658
EndBlockNum uint64 `json:"ending_block_number"`
626
659
}
627
660
628
- func (h * Handler ) sendReorg (w jsonrpc.Conn , reorg * sync .ReorgBlockRange , id uint64 ) error {
661
+ func (h * Handler ) sendReorg (w jsonrpc.Conn , reorg * junoSync .ReorgBlockRange , id uint64 ) error {
629
662
resp , err := json .Marshal (jsonrpc.Request {
630
663
Version : "2.0" ,
631
664
Method : "starknet_subscriptionReorg" ,
0 commit comments