Ejemplo n.º 1
0
        public async Task ProcessAttestationDutiesAsync(Slot slot, CancellationToken cancellationToken)
        {
            // If attester, get attestation, sign attestation, return to node

            IList <(BlsPublicKey, CommitteeIndex)>
            attestationDutyList = _validatorState.GetAttestationDutyForSlot(slot);

            foreach ((BlsPublicKey validatorPublicKey, CommitteeIndex index) in attestationDutyList)
            {
                Activity activity = new Activity("process-attestation-duty");
                activity.Start();
                using IDisposable activityScope = _logger.BeginScope("[TraceId, {TraceId}], [SpanId, {SpanId}]",
                                                                     activity.TraceId, activity.SpanId);
                try
                {
                    if (_logger.IsDebug())
                    {
                        LogDebug.RequestingAttestationFor(_logger, slot, _beaconChainInformation.Time,
                                                          validatorPublicKey,
                                                          null);
                    }

                    ApiResponse <Attestation> newAttestationResponse = await _beaconNodeApi
                                                                       .NewAttestationAsync(validatorPublicKey, false, slot, index, cancellationToken)
                                                                       .ConfigureAwait(false);

                    if (newAttestationResponse.StatusCode == StatusCode.Success)
                    {
                        Attestation  unsignedAttestation  = newAttestationResponse.Content;
                        BlsSignature attestationSignature =
                            await GetAttestationSignatureAsync(unsignedAttestation, validatorPublicKey)
                            .ConfigureAwait(false);

                        Attestation signedAttestation = new Attestation(unsignedAttestation.AggregationBits,
                                                                        unsignedAttestation.Data, attestationSignature);

                        // TODO: Getting one attestation at a time probably isn't very scalable.
                        // All validators are attesting the same data, just in different committees with different indexes
                        // => Get the data once, group relevant validators by committee, sign and aggregate within each
                        // committee (marking relevant aggregation bits), then publish one pre-aggregated value?

                        if (_logger.IsDebug())
                        {
                            LogDebug.PublishingSignedAttestation(_logger, slot, index,
                                                                 validatorPublicKey.ToShortString(),
                                                                 signedAttestation.Data,
                                                                 signedAttestation.Signature.ToString().Substring(0, 10), null);
                        }

                        ApiResponse publishAttestationResponse = await _beaconNodeApi
                                                                 .PublishAttestationAsync(signedAttestation, cancellationToken)
                                                                 .ConfigureAwait(false);

                        if (publishAttestationResponse.StatusCode != StatusCode.Success &&
                            publishAttestationResponse.StatusCode !=
                            StatusCode.BroadcastButFailedValidation)
                        {
                            throw new Exception(
                                      $"Error response from publish: {(int) publishAttestationResponse.StatusCode} {publishAttestationResponse.StatusCode}.");
                        }

                        bool nodeAccepted = publishAttestationResponse.StatusCode == StatusCode.Success;
                        // TODO: Log warning if not accepted? Not sure what else we could do.
                    }
                }
                catch (Exception ex)
                {
                    Log.ExceptionProcessingAttestationDuty(_logger, slot, validatorPublicKey, ex.Message, ex);
                }
                finally
                {
                    activity.Stop();
                }

                _validatorState.ClearAttestationDutyForSlot(slot);
            }
        }