public void ProcessBlockHeader(BeaconState state, BeaconBlock block) { _logger.LogInformation(Event.ProcessBlock, "Process block header for block {BeaconBlock}", block); // Verify that the slots match if (block.Slot != state.Slot) { throw new ArgumentOutOfRangeException("block.Slot", block.Slot, $"Block slot must match state slot {state.Slot}."); } // Verify that the parent matches var latestBlockSigningRoot = state.LatestBlockHeader.SigningRoot(); if (block.ParentRoot != latestBlockSigningRoot) { throw new ArgumentOutOfRangeException("block.ParentRoot", block.ParentRoot, $"Block parent root must match latest block header root {latestBlockSigningRoot}."); } // Save current block as the new latest block var bodyRoot = block.Body.HashTreeRoot(_miscellaneousParameterOptions.CurrentValue, _maxOperationsPerBlockOptions.CurrentValue); var newBlockHeader = new BeaconBlockHeader(block.Slot, block.ParentRoot, Hash32.Zero, // `state_root` is zeroed and overwritten in the next `process_slot` call bodyRoot, new BlsSignature() //`signature` is zeroed ); state.SetLatestBlockHeader(newBlockHeader); // Verify proposer is not slashed var beaconProposerIndex = _beaconStateAccessor.GetBeaconProposerIndex(state); var proposer = state.Validators[(int)(ulong)beaconProposerIndex]; if (proposer.IsSlashed) { throw new Exception("Beacon proposer must not be slashed."); } // Verify proposer signature var signingRoot = block.SigningRoot(_miscellaneousParameterOptions.CurrentValue, _maxOperationsPerBlockOptions.CurrentValue); var domain = _beaconStateAccessor.GetDomain(state, _signatureDomainOptions.CurrentValue.BeaconProposer, Epoch.None); var validSignature = _cryptographyService.BlsVerify(proposer.PublicKey, signingRoot, block.Signature, domain); if (!validSignature) { throw new Exception($"Block signature must match proposer public key {proposer.PublicKey}"); } }