github.com/core-coin/go-core/v2@v2.1.9/les/sync_test.go (about) 1 // Copyright 2019 by the Authors 2 // This file is part of the go-core library. 3 // 4 // The go-core library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-core library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-core library. If not, see <http://www.gnu.org/licenses/>. 16 17 package les 18 19 import ( 20 "fmt" 21 "math/big" 22 "testing" 23 "time" 24 25 "github.com/core-coin/go-core/v2/accounts/abi/bind" 26 "github.com/core-coin/go-core/v2/core" 27 "github.com/core-coin/go-core/v2/crypto" 28 "github.com/core-coin/go-core/v2/light" 29 "github.com/core-coin/go-core/v2/params" 30 ) 31 32 // Test light syncing which will download all headers from genesis. 33 func TestLightSyncingLes3(t *testing.T) { testCheckpointSyncing(t, 3, 0) } 34 35 // Test legacy checkpoint syncing which will download tail headers 36 // based on a hardcoded checkpoint. 37 func TestLegacyCheckpointSyncingLes3(t *testing.T) { testCheckpointSyncing(t, 3, 1) } 38 39 // Test checkpoint syncing which will download tail headers based 40 // on a verified checkpoint. 41 func TestCheckpointSyncingLes3(t *testing.T) { 42 t.Skip("reimplement CheckpointOralce with ed448") 43 testCheckpointSyncing(t, 3, 2) 44 } 45 46 func testCheckpointSyncing(t *testing.T, protocol int, syncMode int) { 47 config := light.TestServerIndexerConfig 48 49 waitIndexers := func(cIndexer, bIndexer, btIndexer *core.ChainIndexer) { 50 for { 51 cs, _, _ := cIndexer.Sections() 52 bts, _, _ := btIndexer.Sections() 53 if cs >= 1 && bts >= 1 { 54 break 55 } 56 time.Sleep(10 * time.Millisecond) 57 } 58 } 59 // Generate 128+1 blocks (totally 1 CHT sections) 60 server, client, tearDown := newClientServerEnv(t, int(config.ChtSize+config.ChtConfirms), protocol, waitIndexers, nil, 0, false, false, true) 61 defer tearDown() 62 63 expected := config.ChtSize + config.ChtConfirms 64 65 // Checkpoint syncing or legacy checkpoint syncing. 66 if syncMode == 1 || syncMode == 2 { 67 // Assemble checkpoint 0 68 s, _, head := server.chtIndexer.Sections() 69 cp := ¶ms.TrustedCheckpoint{ 70 SectionIndex: 0, 71 SectionHead: head, 72 CHTRoot: light.GetChtRoot(server.db, s-1, head), 73 BloomRoot: light.GetBloomTrieRoot(server.db, s-1, head), 74 } 75 if syncMode == 1 { 76 // Register the assembled checkpoint as hardcoded one. 77 client.handler.checkpoint = cp 78 client.handler.backend.blockchain.AddTrustedCheckpoint(cp) 79 } else { 80 // Register the assembled checkpoint into oracle. 81 header := server.backend.Blockchain().CurrentHeader() 82 83 data := append([]byte{0x19, 0x00}, append(registrarAddr.Bytes(), append([]byte{0, 0, 0, 0, 0, 0, 0, 0}, cp.Hash().Bytes()...)...)...) 84 sig, _ := crypto.Sign(crypto.SHA3(data), signerKey) 85 auth, _ := bind.NewKeyedTransactorWithNetworkID(signerKey, big.NewInt(1)) 86 if _, err := server.handler.server.oracle.Contract().RegisterCheckpoint(auth, cp.SectionIndex, cp.Hash().Bytes(), new(big.Int).Sub(header.Number, big.NewInt(1)), header.ParentHash, [][]byte{sig}); err != nil { 87 t.Error("register checkpoint failed", err) 88 } 89 server.backend.Commit() 90 91 // Wait for the checkpoint registration 92 for { 93 _, hash, _, err := server.handler.server.oracle.Contract().Contract().GetLatestCheckpoint(nil) 94 if err != nil || hash == [32]byte{} { 95 time.Sleep(10 * time.Millisecond) 96 continue 97 } 98 break 99 } 100 expected += 1 101 } 102 } 103 104 done := make(chan error) 105 client.handler.syncDone = func() { 106 header := client.handler.backend.blockchain.CurrentHeader() 107 if header.Number.Uint64() == expected { 108 done <- nil 109 } else { 110 done <- fmt.Errorf("blockchain length mismatch, want %d, got %d", expected, header.Number) 111 } 112 } 113 114 // Create connected peer pair. 115 peer1, peer2, err := newTestPeerPair("peer", protocol, server.handler, client.handler) 116 if err != nil { 117 t.Fatalf("Failed to connect testing peers %v", err) 118 } 119 defer peer1.close() 120 defer peer2.close() 121 122 select { 123 case err := <-done: 124 if err != nil { 125 t.Error("sync failed", err) 126 } 127 return 128 case <-time.NewTimer(10 * time.Second).C: 129 t.Error("checkpoint syncing timeout") 130 } 131 } 132 133 func TestMissOracleBackend(t *testing.T) { testMissOracleBackend(t, true) } 134 func TestMissOracleBackendNoCheckpoint(t *testing.T) { testMissOracleBackend(t, false) } 135 136 func testMissOracleBackend(t *testing.T, hasCheckpoint bool) { 137 t.Skip("reimplement CheckpointOralce with ed448") 138 config := light.TestServerIndexerConfig 139 140 waitIndexers := func(cIndexer, bIndexer, btIndexer *core.ChainIndexer) { 141 for { 142 cs, _, _ := cIndexer.Sections() 143 bts, _, _ := btIndexer.Sections() 144 if cs >= 1 && bts >= 1 { 145 break 146 } 147 time.Sleep(10 * time.Millisecond) 148 } 149 } 150 // Generate 512+4 blocks (totally 1 CHT sections) 151 server, client, tearDown := newClientServerEnv(t, int(config.ChtSize+config.ChtConfirms), 3, waitIndexers, nil, 0, false, false, true) 152 defer tearDown() 153 154 expected := config.ChtSize + config.ChtConfirms 155 156 s, _, head := server.chtIndexer.Sections() 157 cp := ¶ms.TrustedCheckpoint{ 158 SectionIndex: 0, 159 SectionHead: head, 160 CHTRoot: light.GetChtRoot(server.db, s-1, head), 161 BloomRoot: light.GetBloomTrieRoot(server.db, s-1, head), 162 } 163 // Register the assembled checkpoint into oracle. 164 header := server.backend.Blockchain().CurrentHeader() 165 166 data := append([]byte{0x19, 0x00}, append(registrarAddr.Bytes(), append([]byte{0, 0, 0, 0, 0, 0, 0, 0}, cp.Hash().Bytes()...)...)...) 167 sig, _ := crypto.Sign(crypto.SHA3(data), signerKey) 168 auth, _ := bind.NewKeyedTransactorWithNetworkID(signerKey, big.NewInt(1)) 169 if _, err := server.handler.server.oracle.Contract().RegisterCheckpoint(auth, cp.SectionIndex, cp.Hash().Bytes(), new(big.Int).Sub(header.Number, big.NewInt(1)), header.ParentHash, [][]byte{sig}); err != nil { 170 t.Error("register checkpoint failed", err) 171 } 172 server.backend.Commit() 173 174 // Wait for the checkpoint registration 175 for { 176 _, hash, _, err := server.handler.server.oracle.Contract().Contract().GetLatestCheckpoint(nil) 177 if err != nil || hash == [32]byte{} { 178 time.Sleep(100 * time.Millisecond) 179 continue 180 } 181 break 182 } 183 expected += 1 184 185 // Explicitly set the oracle as nil. In normal use case it can happen 186 // that user wants to unlock something which blocks the oracle backend 187 // initialisation. But at the same time syncing starts. 188 // 189 // See https://github.com/core-coin/go-core/v2/issues/20097 for more detail. 190 // 191 // In this case, client should run light sync or legacy checkpoint sync 192 // if hardcoded checkpoint is configured. 193 client.handler.backend.oracle = nil 194 195 // For some private networks it can happen checkpoint syncing is enabled 196 // but there is no hardcoded checkpoint configured. 197 if hasCheckpoint { 198 client.handler.checkpoint = cp 199 client.handler.backend.blockchain.AddTrustedCheckpoint(cp) 200 } 201 202 done := make(chan error) 203 client.handler.syncDone = func() { 204 header := client.handler.backend.blockchain.CurrentHeader() 205 if header.Number.Uint64() == expected { 206 done <- nil 207 } else { 208 done <- fmt.Errorf("blockchain length mismatch, want %d, got %d", expected, header.Number) 209 } 210 } 211 // Create connected peer pair. 212 if _, _, err := newTestPeerPair("peer", 2, server.handler, client.handler); err != nil { 213 t.Fatalf("Failed to connect testing peers %v", err) 214 } 215 select { 216 case err := <-done: 217 if err != nil { 218 t.Error("sync failed", err) 219 } 220 return 221 case <-time.NewTimer(10 * time.Second).C: 222 t.Error("checkpoint syncing timeout") 223 } 224 }