public Slot GetCurrentSlot(BeaconChainInformation beaconChainInformation)
        {
            ulong slotValue = (beaconChainInformation.Time - beaconChainInformation.GenesisTime) /
                              _timeParameterOptions.CurrentValue.SecondsPerSlot;

            return(new Slot(slotValue));
        }
Example #2
0
        public Slot GetNextAttestationSlotToCheck(BeaconChainInformation beaconChainInformation)
        {
            // Generally no point in attesting for slots <= current (head) slot
            Slot slotToCheckAttestation =
                Slot.Max(beaconChainInformation.LastAttestationSlotChecked + Slot.One,
                         beaconChainInformation.SyncStatus.CurrentSlot);

            return(slotToCheckAttestation);
        }
Example #3
0
        public ulong GetAttestationTime(BeaconChainInformation beaconChainInformation, Slot slot)
        {
            TimeParameters timeParameters  = _timeParameterOptions.CurrentValue;
            ulong          startTimeOfSlot = beaconChainInformation.GenesisTime + timeParameters.SecondsPerSlot * slot;

            // Attest 1/3 way through slot
            ulong attestationTime = startTimeOfSlot + (_timeParameterOptions.CurrentValue.SecondsPerSlot / 3);

            return(attestationTime);
        }
Example #4
0
 public HonestValidatorWorker(ILogger <HonestValidatorWorker> logger,
                              IClock clock,
                              IHostEnvironment environment,
                              DataDirectory dataDirectory,
                              IBeaconNodeApi beaconNodeApi,
                              BeaconChainInformation beaconChainInformation,
                              ValidatorClient validatorClient,
                              IClientVersion clientVersion)
 {
     _logger                 = logger;
     _clock                  = clock;
     _environment            = environment;
     _dataDirectory          = dataDirectory;
     _beaconNodeApi          = beaconNodeApi;
     _beaconChainInformation = beaconChainInformation;
     _validatorClient        = validatorClient;
     _clientVersion          = clientVersion;
 }
Example #5
0
        public ValidatorClient(ILogger <ValidatorClient> logger,
                               IOptionsMonitor <InitialValues> initialValueOptions,
                               IOptionsMonitor <TimeParameters> timeParameterOptions,
                               IOptionsMonitor <SignatureDomains> signatureDomainOptions,
                               ICryptographyService cryptographyService,
                               IBeaconNodeApi beaconNodeApi,
                               IValidatorKeyProvider validatorKeyProvider,
                               BeaconChainInformation beaconChainInformation)
        {
            _logger = logger;
            _initialValueOptions    = initialValueOptions;
            _timeParameterOptions   = timeParameterOptions;
            _signatureDomainOptions = signatureDomainOptions;
            _cryptographyService    = cryptographyService;
            _beaconNodeApi          = beaconNodeApi;
            _validatorKeyProvider   = validatorKeyProvider;
            _beaconChainInformation = beaconChainInformation;

            _validatorState = new ValidatorState();
            _cache          = new MemoryCache(new MemoryCacheOptions());
        }
        public ValidatorClient(ILogger <ValidatorClient> logger,
                               IOptionsMonitor <MiscellaneousParameters> miscellaneousParameterOptions,
                               IOptionsMonitor <InitialValues> initialValueOptions,
                               IOptionsMonitor <TimeParameters> timeParameterOptions,
                               IOptionsMonitor <MaxOperationsPerBlock> maxOperationsPerBlockOptions,
                               IOptionsMonitor <SignatureDomains> signatureDomainOptions,
                               ICryptographyService cryptographyService,
                               IBeaconNodeApi beaconNodeApi,
                               IValidatorKeyProvider validatorKeyProvider,
                               BeaconChainInformation beaconChainInformation)
        {
            _logger = logger;
            _miscellaneousParameterOptions = miscellaneousParameterOptions;
            _initialValueOptions           = initialValueOptions;
            _timeParameterOptions          = timeParameterOptions;
            _maxOperationsPerBlockOptions  = maxOperationsPerBlockOptions;
            _signatureDomainOptions        = signatureDomainOptions;
            _cryptographyService           = cryptographyService;
            _beaconNodeApi          = beaconNodeApi;
            _validatorKeyProvider   = validatorKeyProvider;
            _beaconChainInformation = beaconChainInformation;

            _validatorState = new ValidatorState();
        }
        public async Task OnTickAsync(BeaconChainInformation beaconChainInformation, ulong time,
                                      CancellationToken cancellationToken)
        {
            // update time
            await beaconChainInformation.SetTimeAsync(time).ConfigureAwait(false);

            Slot currentSlot = GetCurrentSlot(beaconChainInformation);

            // TODO: attestation is done 1/3 way through slot

            // Not a new slot (clock is still the same as the slot we just checked), return
            bool shouldCheckSlot = currentSlot > beaconChainInformation.LastSlotChecked;

            if (!shouldCheckSlot)
            {
                return;
            }

            await UpdateForkVersionActivityAsync(cancellationToken).ConfigureAwait(false);

            // TODO: For beacon nodes that don't report SyncingStatus (which is nullable/optional),
            // then need a different strategy to determine the current head known by the beacon node.
            // The current code (2020-03-15) will simply start from slot 0 and process 1/second until
            // caught up with clock slot; at 6 seconds/slot, this is 6x faster, i.e. 1 day still takes 4 hours.
            // (okay for testing).
            // Alternative 1: see if the node supports /beacon/head, and use that slot
            // Alternative 2: try UpdateDuties, and if you get 406 DutiesNotAvailableForRequestedEpoch then use a
            // divide & conquer algorithm to determine block to check. (Could be a back off x1, x2, x4, x8, etc if 406)

            await UpdateSyncStatusActivityAsync(cancellationToken).ConfigureAwait(false);

            // Need to have an anchor block (will provide the genesis time) before can do anything
            // Absolutely no point in generating blocks < anchor slot
            // Irrespective of clock time, can't check duties >= 2 epochs ahead of current (head), as don't have data
            //  - actually, validator only cares about what they need to sign this slot
            //  - the beacon node takes care of subscribing to topics an epoch in advance, etc
            // While signing a block < highest (seen) slot may be a waste, there is no penalty for doing so

            // Generally no point in generating blocks <= current (head) slot
            Slot slotToCheck =
                Slot.Max(beaconChainInformation.LastSlotChecked, beaconChainInformation.SyncStatus.CurrentSlot) +
                Slot.One;

            LogDebug.ProcessingSlot(_logger, slotToCheck, currentSlot, beaconChainInformation.SyncStatus.CurrentSlot,
                                    null);

            // Slot is set before processing; if there is an error (in process; update duties has a try/catch), it will skip to the next slot
            // (maybe the error will be resolved; trade off of whether error can be fixed by retrying, e.g. network error,
            // but potentially getting stuck in a slot, vs missing a slot)
            // TODO: Maybe add a retry policy/retry count when to advance last slot checked regardless
            await beaconChainInformation.SetLastSlotChecked(slotToCheck);

            // TODO: Attestations should run checks one epoch ahead, for topic subscriptions, although this is more a beacon node thing to do.

            // Note that UpdateDuties will continue even if there is an error/issue (i.e. assume no change and process what we have)
            Epoch epochToCheck = ComputeEpochAtSlot(slotToCheck);

            await UpdateDutiesActivityAsync(epochToCheck, cancellationToken).ConfigureAwait(false);

            await ProcessProposalDutiesAsync(slotToCheck, cancellationToken).ConfigureAwait(false);

            // If upcoming attester, join (or change) topics
            // Subscribe to topics

            // Attest 1/3 way through slot
        }