@@ -102,7 +102,7 @@ func testCheckpointSyncing(t *testing.T, protocol int, syncMode int) {
102102 }
103103
104104 done := make (chan error )
105- client .handler .backend . oracle . syncDoneHook = func () {
105+ client .handler .syncDone = func () {
106106 header := client .handler .backend .blockchain .CurrentHeader ()
107107 if header .Number .Uint64 () == expected {
108108 done <- nil
@@ -131,3 +131,102 @@ func testCheckpointSyncing(t *testing.T, protocol int, syncMode int) {
131131 t .Error ("checkpoint syncing timeout" )
132132 }
133133}
134+
135+ func TestMissOracleBackend (t * testing.T ) { testMissOracleBackend (t , true ) }
136+ func TestMissOracleBackendNoCheckpoint (t * testing.T ) { testMissOracleBackend (t , false ) }
137+
138+ func testMissOracleBackend (t * testing.T , hasCheckpoint bool ) {
139+ config := light .TestServerIndexerConfig
140+
141+ waitIndexers := func (cIndexer , bIndexer , btIndexer * core.ChainIndexer ) {
142+ for {
143+ cs , _ , _ := cIndexer .Sections ()
144+ bts , _ , _ := btIndexer .Sections ()
145+ if cs >= 1 && bts >= 1 {
146+ break
147+ }
148+ time .Sleep (10 * time .Millisecond )
149+ }
150+ }
151+ // Generate 512+4 blocks (totally 1 CHT sections)
152+ server , client , tearDown := newClientServerEnv (t , int (config .ChtSize + config .ChtConfirms ), 3 , waitIndexers , nil , 0 , false , false )
153+ defer tearDown ()
154+
155+ expected := config .ChtSize + config .ChtConfirms
156+
157+ s , _ , head := server .chtIndexer .Sections ()
158+ cp := & params.TrustedCheckpoint {
159+ SectionIndex : 0 ,
160+ SectionHead : head ,
161+ CHTRoot : light .GetChtRoot (server .db , s - 1 , head ),
162+ BloomRoot : light .GetBloomTrieRoot (server .db , s - 1 , head ),
163+ }
164+ // Register the assembled checkpoint into oracle.
165+ header := server .backend .Blockchain ().CurrentHeader ()
166+
167+ data := append ([]byte {0x19 , 0x00 }, append (registrarAddr .Bytes (), append ([]byte {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, cp .Hash ().Bytes ()... )... )... )
168+ sig , _ := crypto .Sign (crypto .Keccak256 (data ), signerKey )
169+ sig [64 ] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
170+ if _ , err := server .handler .server .oracle .contract .RegisterCheckpoint (bind .NewKeyedTransactor (signerKey ), cp .SectionIndex , cp .Hash ().Bytes (), new (big.Int ).Sub (header .Number , big .NewInt (1 )), header .ParentHash , [][]byte {sig }); err != nil {
171+ t .Error ("register checkpoint failed" , err )
172+ }
173+ server .backend .Commit ()
174+
175+ // Wait for the checkpoint registration
176+ for {
177+ _ , hash , _ , err := server .handler .server .oracle .contract .Contract ().GetLatestCheckpoint (nil )
178+ if err != nil || hash == [32 ]byte {} {
179+ time .Sleep (100 * time .Millisecond )
180+ continue
181+ }
182+ break
183+ }
184+ expected += 1
185+
186+ // Explicitly set the oracle as nil. In normal use case it can happen
187+ // that user wants to unlock something which blocks the oracle backend
188+ // initialisation. But at the same time syncing starts.
189+ //
190+ // See https://github.com/ethereum/go-ethereum/issues/20097 for more detail.
191+ //
192+ // In this case, client should run light sync or legacy checkpoint sync
193+ // if hardcoded checkpoint is configured.
194+ client .handler .backend .oracle = nil
195+
196+ // For some private networks it can happen checkpoint syncing is enabled
197+ // but there is no hardcoded checkpoint configured.
198+ if hasCheckpoint {
199+ client .handler .checkpoint = cp
200+ client .handler .backend .blockchain .AddTrustedCheckpoint (cp )
201+ }
202+
203+ done := make (chan error )
204+ client .handler .syncDone = func () {
205+ header := client .handler .backend .blockchain .CurrentHeader ()
206+ if header .Number .Uint64 () == expected {
207+ done <- nil
208+ } else {
209+ done <- fmt .Errorf ("blockchain length mismatch, want %d, got %d" , expected , header .Number )
210+ }
211+ }
212+
213+ // Create connected peer pair.
214+ _ , err1 , _ , err2 := newTestPeerPair ("peer" , 2 , server .handler , client .handler )
215+ select {
216+ case <- time .After (time .Millisecond * 100 ):
217+ case err := <- err1 :
218+ t .Fatalf ("peer 1 handshake error: %v" , err )
219+ case err := <- err2 :
220+ t .Fatalf ("peer 2 handshake error: %v" , err )
221+ }
222+
223+ select {
224+ case err := <- done :
225+ if err != nil {
226+ t .Error ("sync failed" , err )
227+ }
228+ return
229+ case <- time .NewTimer (10 * time .Second ).C :
230+ t .Error ("checkpoint syncing timeout" )
231+ }
232+ }
0 commit comments