@@ -429,21 +429,34 @@ func (t *Task) getCommitteeDuties(ctx context.Context, epoch uint64) ([]*v1.Beac
429429}
430430
431431func (t * Task ) generateAndSubmitAttestation (ctx context.Context , slot uint64 , committeeIdx phase0.CommitteeIndex , duties []* validatorDuty ) (int , error ) {
432- client := t .getClient ()
433- if client == nil {
432+ clients := t .getClients ()
433+ if len ( clients ) == 0 {
434434 return 0 , fmt .Errorf ("no client available" )
435435 }
436436
437437 consensusPool := t .ctx .Scheduler .GetServices ().ClientPool ().GetConsensusPool ()
438438 specs := consensusPool .GetBlockCache ().GetSpecs ()
439439 genesis := consensusPool .GetBlockCache ().GetGenesis ()
440440
441- // Get attestation data from beacon node
442- attData , err := client .GetRPCClient ().GetAttestationData (ctx , slot , uint64 (committeeIdx ))
443- if err != nil {
444- return 0 , fmt .Errorf ("failed to get attestation data: %w" , err )
441+ // Get attestation data from beacon node, retry with different clients if needed
442+ var attData * phase0.AttestationData
443+ var lastErr error
444+ for _ , client := range clients {
445+ var err error
446+ attData , err = client .GetRPCClient ().GetAttestationData (ctx , slot , uint64 (committeeIdx ))
447+ if err == nil {
448+ break
449+ }
450+ lastErr = err
451+ t .logger .Debugf ("failed to get attestation data from %s: %v, trying next client" , client .GetName (), err )
452+ }
453+ if attData == nil {
454+ return 0 , fmt .Errorf ("failed to get attestation data from all clients: %w" , lastErr )
445455 }
446456
457+ // Use first client for remaining operations
458+ client := clients [0 ]
459+
447460 // Apply static late head offset if configured (applies to all attestations in this batch)
448461 if t .config .LateHead != 0 {
449462 modifiedData := t .applyLateHead (attData , t .config .LateHead )
@@ -696,18 +709,39 @@ func (t *Task) findChildBlock(parentRoot phase0.Root) *consensus.Block {
696709}
697710
698711func (t * Task ) getClient () * consensus.Client {
712+ clients := t .getClients ()
713+ if len (clients ) == 0 {
714+ return nil
715+ }
716+
717+ return clients [0 ]
718+ }
719+
720+ func (t * Task ) getClients () []* consensus.Client {
699721 clientPool := t .ctx .Scheduler .GetServices ().ClientPool ()
722+ consensusPool := clientPool .GetConsensusPool ()
700723
701724 if t .config .ClientPattern == "" && t .config .ExcludeClientPattern == "" {
702- return clientPool .GetConsensusPool ().GetReadyEndpoint (consensus .AnyClient )
725+ allClients := consensusPool .GetAllEndpoints ()
726+ clients := make ([]* consensus.Client , 0 , len (allClients ))
727+ for _ , c := range allClients {
728+ if consensusPool .IsClientReady (c ) {
729+ clients = append (clients , c )
730+ }
731+ }
732+
733+ return clients
703734 }
704735
705- clients := clientPool .GetClientsByNamePatterns (t .config .ClientPattern , t .config .ExcludeClientPattern )
706- if len (clients ) == 0 {
707- return nil
736+ poolClients := clientPool .GetClientsByNamePatterns (t .config .ClientPattern , t .config .ExcludeClientPattern )
737+ clients := make ([]* consensus.Client , 0 , len (poolClients ))
738+ for _ , c := range poolClients {
739+ if c .ConsensusClient != nil && consensusPool .IsClientReady (c .ConsensusClient ) {
740+ clients = append (clients , c .ConsensusClient )
741+ }
708742 }
709743
710- return clients [ 0 ]. ConsensusClient
744+ return clients
711745}
712746
713747func (t * Task ) mnemonicToSeed (mnemonic string ) (seed []byte , err error ) {
0 commit comments