@@ -3,6 +3,7 @@ package syncer
3
3
import (
4
4
"context"
5
5
"errors"
6
+ "math/big"
6
7
7
8
"github.com/ethereum/go-ethereum/core/types"
8
9
"github.com/ethereum/go-ethereum/log"
@@ -52,17 +53,45 @@ func parseLogs() error {
52
53
}
53
54
54
55
func (s * UnsafeHeadSyncer ) watchLatestUnsafeHead (ctx context.Context ) error {
56
+ var currentBlock * big.Int
55
57
for {
56
58
select {
57
59
case newHeader , ok := <- s .newLatestHeadCh :
58
60
if ! ok {
59
61
return nil
60
62
}
63
+ blockNum := number .BigToBlockNumber (newHeader .Number )
64
+ if currentBlock != nil {
65
+ switch newHeader .Number .Cmp (currentBlock ) {
66
+ case - 1 , 0 :
67
+ prevNum := new (big.Int ).Sub (newHeader .Number , big .NewInt (1 ))
68
+ prevBlockNum := number .BigToBlockNumber (prevNum )
69
+ // Re-emit the previous block, to pre-emptively signal an
70
+ // incoming reorg. Like this a client is able to e.g.
71
+ // rewind changes first before processing the new
72
+ // events of the reorg
73
+ ev := & event.LatestBlock {
74
+ Number : prevBlockNum ,
75
+ BlockHash : newHeader .ParentHash ,
76
+ }
77
+ err := s .Handler (ctx , ev )
78
+ if err != nil {
79
+ // XXX: return or log?
80
+ // return err
81
+ s .Log .Error (
82
+ "handler for `NewLatestBlock` errored" ,
83
+ "error" ,
84
+ err .Error (),
85
+ )
86
+ }
87
+ case 1 :
88
+ // expected
89
+ }
90
+ }
91
+
61
92
// TODO: check bloom filter for topic of all
62
93
// synced handlers and only call them if
63
94
// the bloomfilter retrieves something.
64
-
65
- blockNum := number .BigToBlockNumber (newHeader .Number )
66
95
for _ , h := range s .SyncedHandler {
67
96
// NOTE: this has to be blocking!
68
97
// So whenever this returns, it is expected
@@ -87,6 +116,7 @@ func (s *UnsafeHeadSyncer) watchLatestUnsafeHead(ctx context.Context) error {
87
116
err .Error (),
88
117
)
89
118
}
119
+ currentBlock = newHeader .Number
90
120
case <- ctx .Done ():
91
121
return ctx .Err ()
92
122
}
0 commit comments