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); } } } } }
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); } } }