github.com/prysmaticlabs/prysm@v1.4.4/validator/client/attest_test.go (about) 1 package client 2 3 import ( 4 "context" 5 "encoding/hex" 6 "errors" 7 "reflect" 8 "sync" 9 "testing" 10 "time" 11 12 "github.com/golang/mock/gomock" 13 types "github.com/prysmaticlabs/eth2-types" 14 "github.com/prysmaticlabs/go-bitfield" 15 "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" 16 pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 17 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 18 validatorpb "github.com/prysmaticlabs/prysm/proto/validator/accounts/v2" 19 "github.com/prysmaticlabs/prysm/shared/bls" 20 "github.com/prysmaticlabs/prysm/shared/bytesutil" 21 "github.com/prysmaticlabs/prysm/shared/event" 22 "github.com/prysmaticlabs/prysm/shared/featureconfig" 23 "github.com/prysmaticlabs/prysm/shared/params" 24 "github.com/prysmaticlabs/prysm/shared/testutil" 25 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 26 "github.com/prysmaticlabs/prysm/shared/testutil/require" 27 "github.com/prysmaticlabs/prysm/shared/timeutils" 28 logTest "github.com/sirupsen/logrus/hooks/test" 29 grpc "google.golang.org/grpc" 30 "gopkg.in/d4l3k/messagediff.v1" 31 ) 32 33 func TestRequestAttestation_ValidatorDutiesRequestFailure(t *testing.T) { 34 hook := logTest.NewGlobal() 35 validator, _, validatorKey, finish := setup(t) 36 validator.duties = ðpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{}} 37 defer finish() 38 39 pubKey := [48]byte{} 40 copy(pubKey[:], validatorKey.PublicKey().Marshal()) 41 validator.SubmitAttestation(context.Background(), 30, pubKey) 42 require.LogsContain(t, hook, "Could not fetch validator assignment") 43 } 44 45 func TestAttestToBlockHead_SubmitAttestation_EmptyCommittee(t *testing.T) { 46 hook := logTest.NewGlobal() 47 48 validator, _, validatorKey, finish := setup(t) 49 defer finish() 50 pubKey := [48]byte{} 51 copy(pubKey[:], validatorKey.PublicKey().Marshal()) 52 validator.duties = ðpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{ 53 { 54 PublicKey: validatorKey.PublicKey().Marshal(), 55 CommitteeIndex: 0, 56 Committee: make([]types.ValidatorIndex, 0), 57 ValidatorIndex: 0, 58 }}} 59 validator.SubmitAttestation(context.Background(), 0, pubKey) 60 require.LogsContain(t, hook, "Empty committee") 61 } 62 63 func TestAttestToBlockHead_SubmitAttestation_RequestFailure(t *testing.T) { 64 hook := logTest.NewGlobal() 65 66 validator, m, validatorKey, finish := setup(t) 67 defer finish() 68 validator.duties = ðpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{ 69 { 70 PublicKey: validatorKey.PublicKey().Marshal(), 71 CommitteeIndex: 5, 72 Committee: make([]types.ValidatorIndex, 111), 73 ValidatorIndex: 0, 74 }}} 75 m.validatorClient.EXPECT().GetAttestationData( 76 gomock.Any(), // ctx 77 gomock.AssignableToTypeOf(ðpb.AttestationDataRequest{}), 78 ).Return(ðpb.AttestationData{ 79 BeaconBlockRoot: make([]byte, 32), 80 Target: ðpb.Checkpoint{Root: make([]byte, 32)}, 81 Source: ðpb.Checkpoint{Root: make([]byte, 32)}, 82 }, nil) 83 m.validatorClient.EXPECT().DomainData( 84 gomock.Any(), // ctx 85 gomock.Any(), // epoch2 86 ).Times(2).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/) 87 m.validatorClient.EXPECT().ProposeAttestation( 88 gomock.Any(), // ctx 89 gomock.AssignableToTypeOf(ðpb.Attestation{}), 90 ).Return(nil, errors.New("something went wrong")) 91 92 pubKey := [48]byte{} 93 copy(pubKey[:], validatorKey.PublicKey().Marshal()) 94 validator.SubmitAttestation(context.Background(), 30, pubKey) 95 require.LogsContain(t, hook, "Could not submit attestation to beacon node") 96 } 97 98 func TestAttestToBlockHead_AttestsCorrectly(t *testing.T) { 99 validator, m, validatorKey, finish := setup(t) 100 defer finish() 101 hook := logTest.NewGlobal() 102 validatorIndex := types.ValidatorIndex(7) 103 committee := []types.ValidatorIndex{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10} 104 pubKey := [48]byte{} 105 copy(pubKey[:], validatorKey.PublicKey().Marshal()) 106 validator.duties = ðpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{ 107 { 108 PublicKey: validatorKey.PublicKey().Marshal(), 109 CommitteeIndex: 5, 110 Committee: committee, 111 ValidatorIndex: validatorIndex, 112 }, 113 }} 114 115 beaconBlockRoot := bytesutil.ToBytes32([]byte("A")) 116 targetRoot := bytesutil.ToBytes32([]byte("B")) 117 sourceRoot := bytesutil.ToBytes32([]byte("C")) 118 m.validatorClient.EXPECT().GetAttestationData( 119 gomock.Any(), // ctx 120 gomock.AssignableToTypeOf(ðpb.AttestationDataRequest{}), 121 ).Return(ðpb.AttestationData{ 122 BeaconBlockRoot: beaconBlockRoot[:], 123 Target: ðpb.Checkpoint{Root: targetRoot[:]}, 124 Source: ðpb.Checkpoint{Root: sourceRoot[:], Epoch: 3}, 125 }, nil) 126 127 m.validatorClient.EXPECT().DomainData( 128 gomock.Any(), // ctx 129 gomock.Any(), // epoch 130 ).Times(2).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/) 131 132 var generatedAttestation *ethpb.Attestation 133 m.validatorClient.EXPECT().ProposeAttestation( 134 gomock.Any(), // ctx 135 gomock.AssignableToTypeOf(ðpb.Attestation{}), 136 ).Do(func(_ context.Context, att *ethpb.Attestation, opts ...grpc.CallOption) { 137 generatedAttestation = att 138 }).Return(ðpb.AttestResponse{}, nil /* error */) 139 140 validator.SubmitAttestation(context.Background(), 30, pubKey) 141 142 aggregationBitfield := bitfield.NewBitlist(uint64(len(committee))) 143 aggregationBitfield.SetBitAt(4, true) 144 expectedAttestation := ðpb.Attestation{ 145 Data: ðpb.AttestationData{ 146 BeaconBlockRoot: beaconBlockRoot[:], 147 Target: ðpb.Checkpoint{Root: targetRoot[:]}, 148 Source: ðpb.Checkpoint{Root: sourceRoot[:], Epoch: 3}, 149 }, 150 AggregationBits: aggregationBitfield, 151 Signature: make([]byte, 96), 152 } 153 154 root, err := helpers.ComputeSigningRoot(expectedAttestation.Data, make([]byte, 32)) 155 require.NoError(t, err) 156 157 sig, err := validator.keyManager.Sign(context.Background(), &validatorpb.SignRequest{ 158 PublicKey: validatorKey.PublicKey().Marshal(), 159 SigningRoot: root[:], 160 }) 161 require.NoError(t, err) 162 expectedAttestation.Signature = sig.Marshal() 163 if !reflect.DeepEqual(generatedAttestation, expectedAttestation) { 164 t.Errorf("Incorrectly attested head, wanted %v, received %v", expectedAttestation, generatedAttestation) 165 diff, _ := messagediff.PrettyDiff(expectedAttestation, generatedAttestation) 166 t.Log(diff) 167 } 168 require.LogsDoNotContain(t, hook, "Could not") 169 } 170 171 func TestAttestToBlockHead_BlocksDoubleAtt(t *testing.T) { 172 hook := logTest.NewGlobal() 173 validator, m, validatorKey, finish := setup(t) 174 defer finish() 175 validatorIndex := types.ValidatorIndex(7) 176 committee := []types.ValidatorIndex{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10} 177 pubKey := [48]byte{} 178 copy(pubKey[:], validatorKey.PublicKey().Marshal()) 179 validator.duties = ðpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{ 180 { 181 PublicKey: validatorKey.PublicKey().Marshal(), 182 CommitteeIndex: 5, 183 Committee: committee, 184 ValidatorIndex: validatorIndex, 185 }, 186 }} 187 beaconBlockRoot := bytesutil.ToBytes32([]byte("A")) 188 targetRoot := bytesutil.ToBytes32([]byte("B")) 189 sourceRoot := bytesutil.ToBytes32([]byte("C")) 190 beaconBlockRoot2 := bytesutil.ToBytes32([]byte("D")) 191 192 m.validatorClient.EXPECT().GetAttestationData( 193 gomock.Any(), // ctx 194 gomock.AssignableToTypeOf(ðpb.AttestationDataRequest{}), 195 ).Return(ðpb.AttestationData{ 196 BeaconBlockRoot: beaconBlockRoot[:], 197 Target: ðpb.Checkpoint{Root: targetRoot[:], Epoch: 4}, 198 Source: ðpb.Checkpoint{Root: sourceRoot[:], Epoch: 3}, 199 }, nil) 200 m.validatorClient.EXPECT().GetAttestationData( 201 gomock.Any(), // ctx 202 gomock.AssignableToTypeOf(ðpb.AttestationDataRequest{}), 203 ).Return(ðpb.AttestationData{ 204 BeaconBlockRoot: beaconBlockRoot2[:], 205 Target: ðpb.Checkpoint{Root: targetRoot[:], Epoch: 4}, 206 Source: ðpb.Checkpoint{Root: sourceRoot[:], Epoch: 3}, 207 }, nil) 208 m.validatorClient.EXPECT().DomainData( 209 gomock.Any(), // ctx 210 gomock.Any(), // epoch 211 ).Times(4).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/) 212 213 m.validatorClient.EXPECT().ProposeAttestation( 214 gomock.Any(), // ctx 215 gomock.AssignableToTypeOf(ðpb.Attestation{}), 216 ).Return(ðpb.AttestResponse{AttestationDataRoot: make([]byte, 32)}, nil /* error */) 217 218 validator.SubmitAttestation(context.Background(), 30, pubKey) 219 validator.SubmitAttestation(context.Background(), 30, pubKey) 220 require.LogsContain(t, hook, "Failed attestation slashing protection") 221 } 222 223 func TestAttestToBlockHead_BlocksSurroundAtt(t *testing.T) { 224 hook := logTest.NewGlobal() 225 validator, m, validatorKey, finish := setup(t) 226 defer finish() 227 validatorIndex := types.ValidatorIndex(7) 228 committee := []types.ValidatorIndex{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10} 229 pubKey := [48]byte{} 230 copy(pubKey[:], validatorKey.PublicKey().Marshal()) 231 validator.duties = ðpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{ 232 { 233 PublicKey: validatorKey.PublicKey().Marshal(), 234 CommitteeIndex: 5, 235 Committee: committee, 236 ValidatorIndex: validatorIndex, 237 }, 238 }} 239 beaconBlockRoot := bytesutil.ToBytes32([]byte("A")) 240 targetRoot := bytesutil.ToBytes32([]byte("B")) 241 sourceRoot := bytesutil.ToBytes32([]byte("C")) 242 243 m.validatorClient.EXPECT().GetAttestationData( 244 gomock.Any(), // ctx 245 gomock.AssignableToTypeOf(ðpb.AttestationDataRequest{}), 246 ).Return(ðpb.AttestationData{ 247 BeaconBlockRoot: beaconBlockRoot[:], 248 Target: ðpb.Checkpoint{Root: targetRoot[:], Epoch: 2}, 249 Source: ðpb.Checkpoint{Root: sourceRoot[:], Epoch: 1}, 250 }, nil) 251 m.validatorClient.EXPECT().GetAttestationData( 252 gomock.Any(), // ctx 253 gomock.AssignableToTypeOf(ðpb.AttestationDataRequest{}), 254 ).Return(ðpb.AttestationData{ 255 BeaconBlockRoot: beaconBlockRoot[:], 256 Target: ðpb.Checkpoint{Root: targetRoot[:], Epoch: 3}, 257 Source: ðpb.Checkpoint{Root: sourceRoot[:], Epoch: 0}, 258 }, nil) 259 260 m.validatorClient.EXPECT().DomainData( 261 gomock.Any(), // ctx 262 gomock.Any(), // epoch 263 ).Times(4).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/) 264 265 m.validatorClient.EXPECT().ProposeAttestation( 266 gomock.Any(), // ctx 267 gomock.AssignableToTypeOf(ðpb.Attestation{}), 268 ).Return(ðpb.AttestResponse{}, nil /* error */) 269 270 validator.SubmitAttestation(context.Background(), 30, pubKey) 271 validator.SubmitAttestation(context.Background(), 30, pubKey) 272 require.LogsContain(t, hook, "Failed attestation slashing protection") 273 } 274 275 func TestAttestToBlockHead_BlocksSurroundedAtt(t *testing.T) { 276 hook := logTest.NewGlobal() 277 validator, m, validatorKey, finish := setup(t) 278 defer finish() 279 validatorIndex := types.ValidatorIndex(7) 280 pubKey := [48]byte{} 281 copy(pubKey[:], validatorKey.PublicKey().Marshal()) 282 committee := []types.ValidatorIndex{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10} 283 validator.duties = ðpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{ 284 { 285 PublicKey: validatorKey.PublicKey().Marshal(), 286 CommitteeIndex: 5, 287 Committee: committee, 288 ValidatorIndex: validatorIndex, 289 }, 290 }} 291 beaconBlockRoot := bytesutil.ToBytes32([]byte("A")) 292 targetRoot := bytesutil.ToBytes32([]byte("B")) 293 sourceRoot := bytesutil.ToBytes32([]byte("C")) 294 295 m.validatorClient.EXPECT().GetAttestationData( 296 gomock.Any(), // ctx 297 gomock.AssignableToTypeOf(ðpb.AttestationDataRequest{}), 298 ).Return(ðpb.AttestationData{ 299 BeaconBlockRoot: beaconBlockRoot[:], 300 Target: ðpb.Checkpoint{Root: targetRoot[:], Epoch: 3}, 301 Source: ðpb.Checkpoint{Root: sourceRoot[:], Epoch: 0}, 302 }, nil) 303 304 m.validatorClient.EXPECT().DomainData( 305 gomock.Any(), // ctx 306 gomock.Any(), // epoch 307 ).Times(4).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/) 308 309 m.validatorClient.EXPECT().ProposeAttestation( 310 gomock.Any(), // ctx 311 gomock.AssignableToTypeOf(ðpb.Attestation{}), 312 ).Return(ðpb.AttestResponse{}, nil /* error */) 313 314 validator.SubmitAttestation(context.Background(), 30, pubKey) 315 require.LogsDoNotContain(t, hook, failedAttLocalProtectionErr) 316 317 m.validatorClient.EXPECT().GetAttestationData( 318 gomock.Any(), // ctx 319 gomock.AssignableToTypeOf(ðpb.AttestationDataRequest{}), 320 ).Return(ðpb.AttestationData{ 321 BeaconBlockRoot: bytesutil.PadTo([]byte("A"), 32), 322 Target: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte("B"), 32), Epoch: 2}, 323 Source: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte("C"), 32), Epoch: 1}, 324 }, nil) 325 326 validator.SubmitAttestation(context.Background(), 30, pubKey) 327 require.LogsContain(t, hook, "Failed attestation slashing protection") 328 } 329 330 func TestAttestToBlockHead_DoesNotAttestBeforeDelay(t *testing.T) { 331 validator, m, validatorKey, finish := setup(t) 332 defer finish() 333 334 pubKey := [48]byte{} 335 copy(pubKey[:], validatorKey.PublicKey().Marshal()) 336 validator.genesisTime = uint64(timeutils.Now().Unix()) 337 m.validatorClient.EXPECT().GetDuties( 338 gomock.Any(), // ctx 339 gomock.AssignableToTypeOf(ðpb.DutiesRequest{}), 340 gomock.Any(), 341 ).Times(0) 342 343 m.validatorClient.EXPECT().GetAttestationData( 344 gomock.Any(), // ctx 345 gomock.AssignableToTypeOf(ðpb.AttestationDataRequest{}), 346 ).Times(0) 347 348 m.validatorClient.EXPECT().ProposeAttestation( 349 gomock.Any(), // ctx 350 gomock.AssignableToTypeOf(ðpb.Attestation{}), 351 ).Return(ðpb.AttestResponse{}, nil /* error */).Times(0) 352 353 timer := time.NewTimer(1 * time.Second) 354 go validator.SubmitAttestation(context.Background(), 0, pubKey) 355 <-timer.C 356 } 357 358 func TestAttestToBlockHead_DoesAttestAfterDelay(t *testing.T) { 359 validator, m, validatorKey, finish := setup(t) 360 defer finish() 361 362 var wg sync.WaitGroup 363 wg.Add(1) 364 defer wg.Wait() 365 366 validator.genesisTime = uint64(timeutils.Now().Unix()) 367 validatorIndex := types.ValidatorIndex(5) 368 committee := []types.ValidatorIndex{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10} 369 pubKey := [48]byte{} 370 copy(pubKey[:], validatorKey.PublicKey().Marshal()) 371 validator.duties = ðpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{ 372 { 373 PublicKey: validatorKey.PublicKey().Marshal(), 374 CommitteeIndex: 5, 375 Committee: committee, 376 ValidatorIndex: validatorIndex, 377 }}} 378 379 m.validatorClient.EXPECT().GetAttestationData( 380 gomock.Any(), // ctx 381 gomock.AssignableToTypeOf(ðpb.AttestationDataRequest{}), 382 ).Return(ðpb.AttestationData{ 383 BeaconBlockRoot: bytesutil.PadTo([]byte("A"), 32), 384 Target: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte("B"), 32)}, 385 Source: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte("C"), 32), Epoch: 3}, 386 }, nil).Do(func(arg0, arg1 interface{}, arg2 ...grpc.CallOption) { 387 wg.Done() 388 }) 389 390 m.validatorClient.EXPECT().DomainData( 391 gomock.Any(), // ctx 392 gomock.Any(), // epoch 393 ).Times(2).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/) 394 395 m.validatorClient.EXPECT().ProposeAttestation( 396 gomock.Any(), // ctx 397 gomock.Any(), 398 ).Return(ðpb.AttestResponse{}, nil).Times(1) 399 400 validator.SubmitAttestation(context.Background(), 0, pubKey) 401 } 402 403 func TestAttestToBlockHead_CorrectBitfieldLength(t *testing.T) { 404 validator, m, validatorKey, finish := setup(t) 405 defer finish() 406 validatorIndex := types.ValidatorIndex(2) 407 committee := []types.ValidatorIndex{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10} 408 pubKey := [48]byte{} 409 copy(pubKey[:], validatorKey.PublicKey().Marshal()) 410 validator.duties = ðpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{ 411 { 412 PublicKey: validatorKey.PublicKey().Marshal(), 413 CommitteeIndex: 5, 414 Committee: committee, 415 ValidatorIndex: validatorIndex, 416 }}} 417 m.validatorClient.EXPECT().GetAttestationData( 418 gomock.Any(), // ctx 419 gomock.AssignableToTypeOf(ðpb.AttestationDataRequest{}), 420 ).Return(ðpb.AttestationData{ 421 Target: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte("B"), 32)}, 422 Source: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte("C"), 32), Epoch: 3}, 423 BeaconBlockRoot: make([]byte, 32), 424 }, nil) 425 426 m.validatorClient.EXPECT().DomainData( 427 gomock.Any(), // ctx 428 gomock.Any(), // epoch 429 ).Times(2).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/) 430 431 var generatedAttestation *ethpb.Attestation 432 m.validatorClient.EXPECT().ProposeAttestation( 433 gomock.Any(), // ctx 434 gomock.AssignableToTypeOf(ðpb.Attestation{}), 435 ).Do(func(_ context.Context, att *ethpb.Attestation, arg2 ...grpc.CallOption) { 436 generatedAttestation = att 437 }).Return(ðpb.AttestResponse{}, nil /* error */) 438 439 validator.SubmitAttestation(context.Background(), 30, pubKey) 440 441 assert.Equal(t, 2, len(generatedAttestation.AggregationBits)) 442 } 443 444 func TestSignAttestation(t *testing.T) { 445 validator, m, _, finish := setup(t) 446 defer finish() 447 448 secretKey, err := bls.SecretKeyFromBytes(bytesutil.PadTo([]byte{1}, 32)) 449 require.NoError(t, err, "Failed to generate key from bytes") 450 publicKey := secretKey.PublicKey() 451 wantedFork := &pb.Fork{ 452 PreviousVersion: []byte{'a', 'b', 'c', 'd'}, 453 CurrentVersion: []byte{'d', 'e', 'f', 'f'}, 454 Epoch: 0, 455 } 456 genesisValidatorRoot := [32]byte{0x01, 0x02} 457 attesterDomain, err := helpers.Domain(wantedFork, 0, params.BeaconConfig().DomainBeaconAttester, genesisValidatorRoot[:]) 458 require.NoError(t, err) 459 m.validatorClient.EXPECT(). 460 DomainData(gomock.Any(), gomock.Any()). 461 Return(ðpb.DomainResponse{SignatureDomain: attesterDomain}, nil) 462 ctx := context.Background() 463 att := testutil.NewAttestation() 464 att.Data.Source.Epoch = 100 465 att.Data.Target.Epoch = 200 466 att.Data.Slot = 999 467 att.Data.BeaconBlockRoot = bytesutil.PadTo([]byte("blockRoot"), 32) 468 var pubKey [48]byte 469 copy(pubKey[:], publicKey.Marshal()) 470 km := &mockKeymanager{ 471 keysMap: map[[48]byte]bls.SecretKey{ 472 pubKey: secretKey, 473 }, 474 } 475 validator.keyManager = km 476 sig, sr, err := validator.signAtt(ctx, pubKey, att.Data) 477 require.NoError(t, err, "%x,%x,%v", sig, sr, err) 478 require.Equal(t, "b6a60f8497bd328908be83634d045"+ 479 "dd7a32f5e246b2c4031fc2f316983f362e36fc27fd3d6d5a2b15"+ 480 "b4dbff38804ffb10b1719b7ebc54e9cbf3293fd37082bc0fc91f"+ 481 "79d70ce5b04ff13de3c8e10bb41305bfdbe921a43792c12624f2"+ 482 "25ee865", hex.EncodeToString(sig)) 483 // proposer domain 484 require.DeepEqual(t, "02bbdb88056d6cbafd6e94575540"+ 485 "e74b8cf2c0f2c1b79b8e17e7b21ed1694305", hex.EncodeToString(sr[:])) 486 } 487 488 func TestServer_WaitToSlotOneThird_CanWait(t *testing.T) { 489 currentTime := uint64(time.Now().Unix()) 490 currentSlot := types.Slot(4) 491 genesisTime := currentTime - uint64(currentSlot.Mul(params.BeaconConfig().SecondsPerSlot)) 492 493 v := &validator{ 494 genesisTime: genesisTime, 495 blockFeed: new(event.Feed), 496 } 497 498 timeToSleep := params.BeaconConfig().SecondsPerSlot / 3 499 oneThird := currentTime + timeToSleep 500 v.waitOneThirdOrValidBlock(context.Background(), currentSlot) 501 502 if oneThird != uint64(time.Now().Unix()) { 503 t.Errorf("Wanted %d time for slot one third but got %d", oneThird, currentTime) 504 } 505 } 506 507 func TestServer_WaitToSlotOneThird_SameReqSlot(t *testing.T) { 508 currentTime := uint64(time.Now().Unix()) 509 currentSlot := types.Slot(4) 510 genesisTime := currentTime - uint64(currentSlot.Mul(params.BeaconConfig().SecondsPerSlot)) 511 512 v := &validator{ 513 genesisTime: genesisTime, 514 blockFeed: new(event.Feed), 515 highestValidSlot: currentSlot, 516 } 517 518 v.waitOneThirdOrValidBlock(context.Background(), currentSlot) 519 520 if currentTime != uint64(time.Now().Unix()) { 521 t.Errorf("Wanted %d time for slot one third but got %d", uint64(time.Now().Unix()), currentTime) 522 } 523 } 524 525 func TestServer_WaitToSlotOneThird_ReceiveBlockSlot(t *testing.T) { 526 resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{AttestTimely: true}) 527 defer resetCfg() 528 529 currentTime := uint64(time.Now().Unix()) 530 currentSlot := types.Slot(4) 531 genesisTime := currentTime - uint64(currentSlot.Mul(params.BeaconConfig().SecondsPerSlot)) 532 533 v := &validator{ 534 genesisTime: genesisTime, 535 blockFeed: new(event.Feed), 536 } 537 538 wg := &sync.WaitGroup{} 539 wg.Add(1) 540 go func() { 541 v.blockFeed.Send(ðpb.SignedBeaconBlock{ 542 Block: ðpb.BeaconBlock{Slot: currentSlot}, 543 }) 544 wg.Done() 545 }() 546 547 v.waitOneThirdOrValidBlock(context.Background(), currentSlot) 548 549 if currentTime != uint64(time.Now().Unix()) { 550 t.Errorf("Wanted %d time for slot one third but got %d", uint64(time.Now().Unix()), currentTime) 551 } 552 }