Esempio n. 1
0
        public async Task OnBlockAsync(IStore store, SignedBeaconBlock signedBlock)
        {
            MiscellaneousParameters miscellaneousParameters = _miscellaneousParameterOptions.CurrentValue;
            MaxOperationsPerBlock   maxOperationsPerBlock   = _maxOperationsPerBlockOptions.CurrentValue;

            BeaconBlock block     = signedBlock.Message;
            Root        blockRoot = _cryptographyService.HashTreeRoot(block);

            if (_logger.IsInfo())
            {
                Log.OnBlock(_logger, blockRoot, block, signedBlock.Signature, null);
            }

            // Make a copy of the state to avoid mutability issues
            BeaconState parentState = await store.GetBlockStateAsync(block.ParentRoot).ConfigureAwait(false);

            BeaconState preState = BeaconState.Clone(parentState);

            // Blocks cannot be in the future. If they are, their consideration must be delayed until the are in the past.
            ulong storeTime        = store.Time;
            Slot  storeCurrentSlot = GetCurrentSlot(store);

            if (storeCurrentSlot < block.Slot)
            {
                throw new ArgumentOutOfRangeException(nameof(block), block.Slot,
                                                      $"Block slot time cannot be in the future, compared to store time {storeTime} (slot {storeCurrentSlot}, since genesis {store.GenesisTime}.");
            }

            // Add new block to the store
            await store.SetSignedBlockAsync(blockRoot, signedBlock).ConfigureAwait(false);

            // Check that block is later than the finalized epoch slot (optimization to reduce calls to get_ancestor)
            Slot finalizedSlot = _beaconChainUtility.ComputeStartSlotOfEpoch(store.FinalizedCheckpoint.Epoch);

            if (block.Slot <= finalizedSlot)
            {
                throw new ArgumentOutOfRangeException(nameof(block), block.Slot,
                                                      $"Block slot must be later than the finalized epoch start slot {finalizedSlot}.");
            }

            // Check block is a descendant of the finalized block at the checkpoint finalized slot
            Root ancestorOfBlockAtFinalizedSlot =
                await GetAncestorAsync(store, blockRoot, finalizedSlot).ConfigureAwait(false);

            if (!ancestorOfBlockAtFinalizedSlot.Equals(store.FinalizedCheckpoint.Root))
            {
                throw new Exception(
                          $"Block with hash tree root {blockRoot} is not a descendant of the finalized block {store.FinalizedCheckpoint.Root} at slot {finalizedSlot}.");
            }

            // Check the block is valid and compute the post-state
            BeaconState state = _beaconStateTransition.StateTransition(preState, signedBlock, validateResult: true);

            // Add new state for this block to the store
            await store.SetBlockStateAsync(blockRoot, state).ConfigureAwait(false);

            if (_logger.IsDebug())
            {
                LogDebug.AddedBlockToStore(_logger, block, state, blockRoot, null);
            }

            // Update justified checkpoint
            if (state.CurrentJustifiedCheckpoint.Epoch > store.JustifiedCheckpoint.Epoch)
            {
                if (state.CurrentJustifiedCheckpoint.Epoch > store.BestJustifiedCheckpoint.Epoch)
                {
                    await store.SetBestJustifiedCheckpointAsync(state.CurrentJustifiedCheckpoint).ConfigureAwait(false);
                }

                bool shouldUpdateJustifiedCheckpoint =
                    await ShouldUpdateJustifiedCheckpointAsync(store, state.CurrentJustifiedCheckpoint)
                    .ConfigureAwait(false);

                if (shouldUpdateJustifiedCheckpoint)
                {
                    await store.SetJustifiedCheckpointAsync(state.CurrentJustifiedCheckpoint).ConfigureAwait(false);

                    if (_logger.IsDebug())
                    {
                        LogDebug.UpdateJustifiedCheckpoint(_logger, state.CurrentJustifiedCheckpoint, null);
                    }
                }
                else
                {
                    if (_logger.IsDebug())
                    {
                        LogDebug.UpdateBestJustifiedCheckpoint(_logger, state.CurrentJustifiedCheckpoint, null);
                    }
                }
            }

            // Update finalized checkpoint
            if (state.FinalizedCheckpoint.Epoch > store.FinalizedCheckpoint.Epoch)
            {
                await store.SetFinalizedCheckpointAsync(state.FinalizedCheckpoint).ConfigureAwait(false);

                if (_logger.IsDebug())
                {
                    LogDebug.UpdateFinalizedCheckpoint(_logger, state.FinalizedCheckpoint, null);
                }

                // Update justified if new justified is later than store justified
                // or if store justified is not in chain with finalized checkpoint
                if (state.CurrentJustifiedCheckpoint.Epoch > store.JustifiedCheckpoint.Epoch)
                {
                    await store.SetJustifiedCheckpointAsync(state.CurrentJustifiedCheckpoint).ConfigureAwait(false);

                    if (_logger.IsDebug())
                    {
                        LogDebug.UpdateJustifiedCheckpoint(_logger, state.CurrentJustifiedCheckpoint, null);
                    }
                }
                else
                {
                    Slot newFinalizedSlot =
                        _beaconChainUtility.ComputeStartSlotOfEpoch(store.FinalizedCheckpoint.Epoch);
                    Root ancestorOfJustifiedAtNewFinalizedSlot =
                        await GetAncestorAsync(store, store.JustifiedCheckpoint.Root, newFinalizedSlot)
                        .ConfigureAwait(false);

                    if (!ancestorOfJustifiedAtNewFinalizedSlot.Equals(store.FinalizedCheckpoint.Root))
                    {
                        await store.SetJustifiedCheckpointAsync(state.CurrentJustifiedCheckpoint).ConfigureAwait(false);

                        if (_logger.IsDebug())
                        {
                            LogDebug.UpdateJustifiedCheckpoint(_logger, state.CurrentJustifiedCheckpoint, null);
                        }
                    }
                }
            }
        }
Esempio n. 2
0
        public async Task OnBlockAsync(IStore store, BeaconBlock block)
        {
            MiscellaneousParameters miscellaneousParameters = _miscellaneousParameterOptions.CurrentValue;
            MaxOperationsPerBlock   maxOperationsPerBlock   = _maxOperationsPerBlockOptions.CurrentValue;

            Hash32 signingRoot = _cryptographyService.SigningRoot(block);

            if (_logger.IsInfo())
            {
                Log.OnBlock(_logger, signingRoot, block, null);
            }

            // Make a copy of the state to avoid mutability issues
            BeaconState parentState = await store.GetBlockStateAsync(block.ParentRoot).ConfigureAwait(false);

            BeaconState preState = BeaconState.Clone(parentState);

            // Blocks cannot be in the future. If they are, their consideration must be delayed until the are in the past.
            ulong blockTime = preState.GenesisTime + (ulong)block.Slot * _timeParameterOptions.CurrentValue.SecondsPerSlot;

            if (blockTime > store.Time)
            {
                throw new ArgumentOutOfRangeException(nameof(block), blockTime, $"Block slot time cannot be in the future, compared to store time {store.Time}.");
            }

            // Add new block to the store
            await store.SetBlockAsync(signingRoot, block).ConfigureAwait(false);

            // Check block is a descendant of the finalized block
            BeaconBlock finalizedCheckpointBlock = await store.GetBlockAsync(store.FinalizedCheckpoint.Root).ConfigureAwait(false);

            Hash32 ancestor = await GetAncestorAsync(store, signingRoot, finalizedCheckpointBlock !.Slot).ConfigureAwait(false);

            if (ancestor != store.FinalizedCheckpoint.Root)
            {
                throw new Exception($"Block with signing root {signingRoot} is not a descendant of the finalized block {store.FinalizedCheckpoint.Root} at slot {finalizedCheckpointBlock.Slot}.");
            }

            // Check that block is later than the finalized epoch slot
            Slot finalizedEpochStartSlot = _beaconChainUtility.ComputeStartSlotOfEpoch(store.FinalizedCheckpoint.Epoch);

            if (block.Slot <= finalizedEpochStartSlot)
            {
                throw new ArgumentOutOfRangeException(nameof(block), block.Slot, $"Block slot must be later than the finalized epoch start slot {finalizedEpochStartSlot}.");
            }

            // Check the block is valid and compute the post-state
            BeaconState state = _beaconStateTransition.StateTransition(preState, block, validateStateRoot: true);

            // Add new state for this block to the store
            await store.SetBlockStateAsync(signingRoot, state).ConfigureAwait(false);

            if (_logger.IsDebug())
            {
                LogDebug.AddedBlockToStore(_logger, block, state, signingRoot, null);
            }

            // Update justified checkpoint
            if (state.CurrentJustifiedCheckpoint.Epoch > store.JustifiedCheckpoint.Epoch)
            {
                await store.SetBestJustifiedCheckpointAsync(state.CurrentJustifiedCheckpoint).ConfigureAwait(false);

                bool shouldUpdateJustifiedCheckpoint = await ShouldUpdateJustifiedCheckpointAsync(store, state.CurrentJustifiedCheckpoint).ConfigureAwait(false);

                if (shouldUpdateJustifiedCheckpoint)
                {
                    await store.SetJustifiedCheckpointAsync(state.CurrentJustifiedCheckpoint).ConfigureAwait(false);

                    if (_logger.IsDebug())
                    {
                        LogDebug.UpdateJustifiedCheckpoint(_logger, state.CurrentJustifiedCheckpoint, null);
                    }
                }
                else
                {
                    if (_logger.IsDebug())
                    {
                        LogDebug.UpdateBestJustifiedCheckpoint(_logger, state.CurrentJustifiedCheckpoint, null);
                    }
                }
            }

            // Update finalized checkpoint
            if (state.FinalizedCheckpoint.Epoch > store.FinalizedCheckpoint.Epoch)
            {
                await store.SetFinalizedCheckpointAsync(state.FinalizedCheckpoint).ConfigureAwait(false);

                if (_logger.IsDebug())
                {
                    LogDebug.UpdateFinalizedCheckpoint(_logger, state.FinalizedCheckpoint, null);
                }
            }
        }