github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/sync/service_test.go (about) 1 package sync 2 3 import ( 4 "context" 5 "sync" 6 "testing" 7 "time" 8 9 gcache "github.com/patrickmn/go-cache" 10 mockChain "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" 11 "github.com/prysmaticlabs/prysm/beacon-chain/core/feed" 12 statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" 13 p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" 14 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" 15 mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" 16 pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 17 "github.com/prysmaticlabs/prysm/shared/abool" 18 "github.com/prysmaticlabs/prysm/shared/bls" 19 "github.com/prysmaticlabs/prysm/shared/bytesutil" 20 "github.com/prysmaticlabs/prysm/shared/testutil" 21 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 22 "github.com/prysmaticlabs/prysm/shared/testutil/require" 23 ) 24 25 func TestService_StatusZeroEpoch(t *testing.T) { 26 bState, err := v1.InitializeFromProto(&pb.BeaconState{Slot: 0}) 27 require.NoError(t, err) 28 r := &Service{ 29 cfg: &Config{ 30 P2P: p2ptest.NewTestP2P(t), 31 InitialSync: new(mockSync.Sync), 32 Chain: &mockChain.ChainService{ 33 Genesis: time.Now(), 34 State: bState, 35 }, 36 }, 37 chainStarted: abool.New(), 38 } 39 r.chainStarted.Set() 40 41 assert.NoError(t, r.Status(), "Wanted non failing status") 42 } 43 44 func TestSyncHandlers_WaitToSync(t *testing.T) { 45 p2p := p2ptest.NewTestP2P(t) 46 chainService := &mockChain.ChainService{ 47 Genesis: time.Now(), 48 ValidatorsRoot: [32]byte{'A'}, 49 } 50 r := Service{ 51 ctx: context.Background(), 52 cfg: &Config{ 53 P2P: p2p, 54 Chain: chainService, 55 StateNotifier: chainService.StateNotifier(), 56 InitialSync: &mockSync.Sync{IsSyncing: false}, 57 }, 58 chainStarted: abool.New(), 59 } 60 61 topic := "/eth2/%x/beacon_block" 62 go r.registerHandlers() 63 time.Sleep(100 * time.Millisecond) 64 i := r.cfg.StateNotifier.StateFeed().Send(&feed.Event{ 65 Type: statefeed.Initialized, 66 Data: &statefeed.InitializedData{ 67 StartTime: time.Now(), 68 }, 69 }) 70 if i == 0 { 71 t.Fatal("didn't send genesis time to subscribers") 72 } 73 b := []byte("sk") 74 b32 := bytesutil.ToBytes32(b) 75 sk, err := bls.SecretKeyFromBytes(b32[:]) 76 require.NoError(t, err) 77 78 msg := testutil.NewBeaconBlock() 79 msg.Block.ParentRoot = testutil.Random32Bytes(t) 80 msg.Signature = sk.Sign([]byte("data")).Marshal() 81 p2p.ReceivePubSub(topic, msg) 82 // wait for chainstart to be sent 83 time.Sleep(400 * time.Millisecond) 84 require.Equal(t, true, r.chainStarted.IsSet(), "Did not receive chain start event.") 85 } 86 87 func TestSyncHandlers_WaitForChainStart(t *testing.T) { 88 p2p := p2ptest.NewTestP2P(t) 89 chainService := &mockChain.ChainService{ 90 Genesis: time.Now(), 91 ValidatorsRoot: [32]byte{'A'}, 92 } 93 r := Service{ 94 ctx: context.Background(), 95 cfg: &Config{ 96 P2P: p2p, 97 Chain: chainService, 98 StateNotifier: chainService.StateNotifier(), 99 InitialSync: &mockSync.Sync{IsSyncing: false}, 100 }, 101 chainStarted: abool.New(), 102 slotToPendingBlocks: gcache.New(time.Second, 2*time.Second), 103 } 104 105 go r.registerHandlers() 106 time.Sleep(100 * time.Millisecond) 107 i := r.cfg.StateNotifier.StateFeed().Send(&feed.Event{ 108 Type: statefeed.Initialized, 109 Data: &statefeed.InitializedData{ 110 StartTime: time.Now().Add(2 * time.Second), 111 }, 112 }) 113 if i == 0 { 114 t.Fatal("didn't send genesis time to subscribers") 115 } 116 require.Equal(t, false, r.chainStarted.IsSet(), "Chainstart was marked prematurely") 117 118 // wait for chainstart to be sent 119 time.Sleep(3 * time.Second) 120 require.Equal(t, true, r.chainStarted.IsSet(), "Did not receive chain start event.") 121 } 122 123 func TestSyncHandlers_WaitTillSynced(t *testing.T) { 124 p2p := p2ptest.NewTestP2P(t) 125 chainService := &mockChain.ChainService{ 126 Genesis: time.Now(), 127 ValidatorsRoot: [32]byte{'A'}, 128 } 129 r := Service{ 130 ctx: context.Background(), 131 cfg: &Config{ 132 P2P: p2p, 133 Chain: chainService, 134 StateNotifier: chainService.StateNotifier(), 135 InitialSync: &mockSync.Sync{IsSyncing: false}, 136 }, 137 chainStarted: abool.New(), 138 } 139 140 topic := "/eth2/%x/beacon_block" 141 go r.registerHandlers() 142 time.Sleep(100 * time.Millisecond) 143 i := r.cfg.StateNotifier.StateFeed().Send(&feed.Event{ 144 Type: statefeed.Initialized, 145 Data: &statefeed.InitializedData{ 146 StartTime: time.Now(), 147 }, 148 }) 149 if i == 0 { 150 t.Fatal("didn't send genesis time to subscribers") 151 } 152 b := []byte("sk") 153 b32 := bytesutil.ToBytes32(b) 154 sk, err := bls.SecretKeyFromBytes(b32[:]) 155 require.NoError(t, err) 156 157 msg := testutil.NewBeaconBlock() 158 msg.Block.ParentRoot = testutil.Random32Bytes(t) 159 msg.Signature = sk.Sign([]byte("data")).Marshal() 160 p2p.Digest, err = r.forkDigest() 161 r.cfg.BlockNotifier = chainService.BlockNotifier() 162 blockChan := make(chan feed.Event, 1) 163 sub := r.cfg.BlockNotifier.BlockFeed().Subscribe(blockChan) 164 165 require.NoError(t, err) 166 p2p.ReceivePubSub(topic, msg) 167 168 // wait for chainstart to be sent 169 time.Sleep(2 * time.Second) 170 require.Equal(t, true, r.chainStarted.IsSet(), "Did not receive chain start event.") 171 172 assert.Equal(t, 0, len(blockChan), "block was received by sync service despite not being fully synced") 173 174 i = r.cfg.StateNotifier.StateFeed().Send(&feed.Event{ 175 Type: statefeed.Synced, 176 Data: &statefeed.SyncedData{ 177 StartTime: time.Now(), 178 }, 179 }) 180 181 if i == 0 { 182 t.Fatal("didn't send genesis time to sync event subscribers") 183 } 184 185 wg := new(sync.WaitGroup) 186 wg.Add(1) 187 go func() { 188 // Wait for block to be received by service. 189 <-blockChan 190 wg.Done() 191 sub.Unsubscribe() 192 }() 193 194 p2p.ReceivePubSub(topic, msg) 195 // wait for message to be sent 196 testutil.WaitTimeout(wg, 2*time.Second) 197 } 198 199 func TestSyncService_StopCleanly(t *testing.T) { 200 p2p := p2ptest.NewTestP2P(t) 201 chainService := &mockChain.ChainService{ 202 Genesis: time.Now(), 203 ValidatorsRoot: [32]byte{'A'}, 204 } 205 ctx, cancel := context.WithCancel(context.Background()) 206 r := Service{ 207 ctx: ctx, 208 cancel: cancel, 209 cfg: &Config{ 210 P2P: p2p, 211 Chain: chainService, 212 StateNotifier: chainService.StateNotifier(), 213 InitialSync: &mockSync.Sync{IsSyncing: false}, 214 }, 215 chainStarted: abool.New(), 216 } 217 218 go r.registerHandlers() 219 time.Sleep(100 * time.Millisecond) 220 i := r.cfg.StateNotifier.StateFeed().Send(&feed.Event{ 221 Type: statefeed.Initialized, 222 Data: &statefeed.InitializedData{ 223 StartTime: time.Now(), 224 }, 225 }) 226 if i == 0 { 227 t.Fatal("didn't send genesis time to subscribers") 228 } 229 230 var err error 231 p2p.Digest, err = r.forkDigest() 232 require.NoError(t, err) 233 234 // wait for chainstart to be sent 235 time.Sleep(2 * time.Second) 236 require.Equal(t, true, r.chainStarted.IsSet(), "Did not receive chain start event.") 237 238 i = r.cfg.StateNotifier.StateFeed().Send(&feed.Event{ 239 Type: statefeed.Synced, 240 Data: &statefeed.SyncedData{ 241 StartTime: time.Now(), 242 }, 243 }) 244 if i == 0 { 245 t.Fatal("didn't send genesis time to sync event subscribers") 246 } 247 248 time.Sleep(1 * time.Second) 249 250 require.NotEqual(t, 0, len(r.cfg.P2P.PubSub().GetTopics())) 251 require.NotEqual(t, 0, len(r.cfg.P2P.Host().Mux().Protocols())) 252 253 // Both pubsub and rpc topcis should be unsubscribed. 254 require.NoError(t, r.Stop()) 255 256 // Sleep to allow pubsub topics to be deregistered. 257 time.Sleep(1 * time.Second) 258 require.Equal(t, 0, len(r.cfg.P2P.PubSub().GetTopics())) 259 require.Equal(t, 0, len(r.cfg.P2P.Host().Mux().Protocols())) 260 }