/// <summary> /// Check if ``indexed_attestation`` has valid indices and signature. /// </summary> public bool IsValidIndexedAttestation(BeaconState state, IndexedAttestation indexedAttestation, Domain domain) { MiscellaneousParameters miscellaneousParameters = _miscellaneousParameterOptions.CurrentValue; IReadOnlyList<ValidatorIndex> attestingIndices = indexedAttestation.AttestingIndices; // Verify max number of indices if ((ulong) attestingIndices.Count > miscellaneousParameters.MaximumValidatorsPerCommittee) { if (_logger.IsWarn()) Log.InvalidIndexedAttestationTooMany(_logger, indexedAttestation.Data.Index, indexedAttestation.Data.Slot, attestingIndices.Count, miscellaneousParameters.MaximumValidatorsPerCommittee, null); return false; } // Verify indices are sorted if (attestingIndices.Count() > 1) { for (int index = 0; index < attestingIndices.Count() - 1; index++) { if (!(attestingIndices[index] < attestingIndices[index + 1])) { if (_logger.IsWarn()) Log.InvalidIndexedAttestationNotSorted(_logger, indexedAttestation.Data.Index, indexedAttestation.Data.Slot, 0, index, null); return false; } } } // Verify aggregate signature IEnumerable<BlsPublicKey> publicKeys = attestingIndices.Select(x => state.Validators[(int) (ulong) x].PublicKey); BlsPublicKey aggregatePublicKey = _cryptographyService.BlsAggregatePublicKeys(publicKeys); Hash32 messageHash = _cryptographyService.HashTreeRoot(indexedAttestation.Data); BlsSignature signature = indexedAttestation.Signature; bool isValid = _cryptographyService.BlsVerify(aggregatePublicKey, messageHash, signature, domain); if (!isValid) { if (_logger.IsWarn()) Log.InvalidIndexedAttestationSignature(_logger, indexedAttestation.Data.Index, indexedAttestation.Data.Slot, null); return false; } return true; }
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}"); } }