Skip to content

Commit

Permalink
Update specs comments (#8750)
Browse files Browse the repository at this point in the history
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Apr 13, 2021
1 parent 8b494fb commit cc9bec7
Show file tree
Hide file tree
Showing 13 changed files with 74 additions and 75 deletions.
2 changes: 1 addition & 1 deletion beacon-chain/core/blocks/attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func ProcessAttestations(
// assert data.source == state.previous_justified_checkpoint
// state.previous_epoch_attestations.append(pending_attestation)
//
// # Check signature
// # Verify signature
// assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation))
func ProcessAttestation(
ctx context.Context,
Expand Down
2 changes: 1 addition & 1 deletion beacon-chain/core/blocks/eth1_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
// def process_eth1_data(state: BeaconState, body: BeaconBlockBody) -> None:
// state.eth1_data_votes.append(body.eth1_data)
// if state.eth1_data_votes.count(body.eth1_data) * 2 > EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH:
// state.latest_eth1_data = body.eth1_data
// state.eth1_data = body.eth1_data
func ProcessEth1DataInBlock(_ context.Context, beaconState iface.BeaconState, b *ethpb.SignedBeaconBlock) (iface.BeaconState, error) {
block := b.Block
if beaconState == nil {
Expand Down
28 changes: 16 additions & 12 deletions beacon-chain/core/blocks/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,24 @@ import (
// def process_block_header(state: BeaconState, block: BeaconBlock) -> None:
// # Verify that the slots match
// assert block.slot == state.slot
// # Verify that proposer index is the correct index
// # Verify that the block is newer than latest block header
// assert block.slot > state.latest_block_header.slot
// # Verify that proposer index is the correct index
// assert block.proposer_index == get_beacon_proposer_index(state)
// # Verify that the parent matches
// assert block.parent_root == hash_tree_root(state.latest_block_header)
// # Save current block as the new latest block
// # Cache current block as the new latest block
// state.latest_block_header = BeaconBlockHeader(
// slot=block.slot,
// proposer_index=block.proposer_index,
// parent_root=block.parent_root,
// # state_root: zeroed, overwritten in the next `process_slot` call
// state_root=Bytes32(), # Overwritten in the next process_slot call
// body_root=hash_tree_root(block.body),
// # signature is always zeroed
// )
//
// # Verify proposer is not slashed
// proposer = state.validators[get_beacon_proposer_index(state)]
// proposer = state.validators[block.proposer_index]
// assert not proposer.slashed
// # Verify proposer signature
// assert bls_verify(proposer.pubkey, signing_root(block), block.signature, get_domain(state, DOMAIN_BEACON_PROPOSER))
func ProcessBlockHeader(
_ context.Context,
beaconState iface.BeaconState,
Expand Down Expand Up @@ -64,20 +65,23 @@ func ProcessBlockHeader(
// def process_block_header(state: BeaconState, block: BeaconBlock) -> None:
// # Verify that the slots match
// assert block.slot == state.slot
// # Verify that proposer index is the correct index
// # Verify that the block is newer than latest block header
// assert block.slot > state.latest_block_header.slot
// # Verify that proposer index is the correct index
// assert block.proposer_index == get_beacon_proposer_index(state)
// # Verify that the parent matches
// assert block.parent_root == hash_tree_root(state.latest_block_header)
// # Save current block as the new latest block
// # Cache current block as the new latest block
// state.latest_block_header = BeaconBlockHeader(
// slot=block.slot,
// proposer_index=block.proposer_index,
// parent_root=block.parent_root,
// # state_root: zeroed, overwritten in the next `process_slot` call
// state_root=Bytes32(), # Overwritten in the next process_slot call
// body_root=hash_tree_root(block.body),
// # signature is always zeroed
// )
//
// # Verify proposer is not slashed
// proposer = state.validators[get_beacon_proposer_index(state)]
// proposer = state.validators[block.proposer_index]
// assert not proposer.slashed
func ProcessBlockHeaderNoVerify(
beaconState iface.BeaconState,
Expand Down
31 changes: 17 additions & 14 deletions beacon-chain/core/blocks/proposer_slashing.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,25 @@ import (
//
// Spec pseudocode definition:
// def process_proposer_slashing(state: BeaconState, proposer_slashing: ProposerSlashing) -> None:
// """
// Process ``ProposerSlashing`` operation.
// """
// proposer = state.validator_registry[proposer_slashing.proposer_index]
// # Verify slots match
// assert proposer_slashing.header_1.slot == proposer_slashing.header_2.slot
// # But the headers are different
// assert proposer_slashing.header_1 != proposer_slashing.header_2
// # Check proposer is slashable
// header_1 = proposer_slashing.signed_header_1.message
// header_2 = proposer_slashing.signed_header_2.message
//
// # Verify header slots match
// assert header_1.slot == header_2.slot
// # Verify header proposer indices match
// assert header_1.proposer_index == header_2.proposer_index
// # Verify the headers are different
// assert header_1 != header_2
// # Verify the proposer is slashable
// proposer = state.validators[header_1.proposer_index]
// assert is_slashable_validator(proposer, get_current_epoch(state))
// # Signatures are valid
// for header in (proposer_slashing.header_1, proposer_slashing.header_2):
// domain = get_domain(state, DOMAIN_BEACON_PROPOSER, slot_to_epoch(header.slot))
// assert bls_verify(proposer.pubkey, signing_root(header), header.signature, domain)
// # Verify signatures
// for signed_header in (proposer_slashing.signed_header_1, proposer_slashing.signed_header_2):
// domain = get_domain(state, DOMAIN_BEACON_PROPOSER, compute_epoch_at_slot(signed_header.message.slot))
// signing_root = compute_signing_root(signed_header.message, domain)
// assert bls.Verify(proposer.pubkey, signing_root, signed_header.signature)
//
// slash_validator(state, proposer_slashing.proposer_index)
// slash_validator(state, header_1.proposer_index)
func ProcessProposerSlashings(
_ context.Context,
beaconState iface.BeaconState,
Expand Down
8 changes: 4 additions & 4 deletions beacon-chain/core/epoch/epoch_processing.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ func ProcessRegistryUpdates(state iface.BeaconState) (iface.BeaconState, error)
// for index, validator in enumerate(state.validators):
// if validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch:
// increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid uint64 overflow
// penalty_numerator = validator.effective_balance // increment * adjusted_total_slashing_balance
// penalty_numerator = validator.effective_balance // increment * adjusted_total_slashing_balance
// penalty = penalty_numerator // total_balance * increment
// decrease_balance(state, ValidatorIndex(index), penalty)
func ProcessSlashings(state iface.BeaconState) (iface.BeaconState, error) {
Expand Down Expand Up @@ -474,9 +474,9 @@ func UnslashedAttestingIndices(state iface.ReadOnlyBeaconState, atts []*pb.Pendi
//
// Spec pseudocode definition:
// def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei:
// total_balance = get_total_active_balance(state)
// effective_balance = state.validator_registry[index].effective_balance
// return effective_balance * BASE_REWARD_FACTOR // integer_squareroot(total_balance) // BASE_REWARDS_PER_EPOCH
// total_balance = get_total_active_balance(state)
// effective_balance = state.validators[index].effective_balance
// return Gwei(effective_balance * BASE_REWARD_FACTOR // integer_squareroot(total_balance) // BASE_REWARDS_PER_EPOCH)
func BaseReward(state iface.ReadOnlyBeaconState, index types.ValidatorIndex) (uint64, error) {
totalBalance, err := helpers.TotalActiveBalance(state)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions beacon-chain/core/helpers/attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func ValidateSlotTargetEpoch(data *ethpb.AttestationData) error {
// def is_aggregator(state: BeaconState, slot: Slot, index: CommitteeIndex, slot_signature: BLSSignature) -> bool:
// committee = get_beacon_committee(state, slot, index)
// modulo = max(1, len(committee) // TARGET_AGGREGATORS_PER_COMMITTEE)
// return bytes_to_int(hash(slot_signature)[0:8]) % modulo == 0
// return bytes_to_uint64(hash(slot_signature)[0:8]) % modulo == 0
func IsAggregator(committeeCount uint64, slotSig []byte) (bool, error) {
modulo := uint64(1)
if committeeCount/params.BeaconConfig().TargetAggregatorsPerCommittee > 1 {
Expand All @@ -69,7 +69,7 @@ func IsAggregator(committeeCount uint64, slotSig []byte) (bool, error) {
// Spec pseudocode definition:
// def get_aggregate_signature(attestations: Sequence[Attestation]) -> BLSSignature:
// signatures = [attestation.signature for attestation in attestations]
// return bls_aggregate_signatures(signatures)
// return bls.Aggregate(signatures)
func AggregateSignature(attestations []*ethpb.Attestation) (bls.Signature, error) {
sigs := make([]bls.Signature, len(attestations))
var err error
Expand Down
10 changes: 5 additions & 5 deletions beacon-chain/core/helpers/committee.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ var proposerIndicesCache = cache.NewProposerIndicesCache()
// """
// Return the number of committees in each slot for the given ``epoch``.
// """
// return max(1, min(
// return max(uint64(1), min(
// MAX_COMMITTEES_PER_SLOT,
// len(get_active_validator_indices(state, epoch)) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE,
// uint64(len(get_active_validator_indices(state, epoch))) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE,
// ))
func SlotCommitteeCount(activeValidatorCount uint64) uint64 {
var committeePerSlot = activeValidatorCount / uint64(params.BeaconConfig().SlotsPerEpoch) / params.BeaconConfig().TargetCommitteeSize
Expand Down Expand Up @@ -121,15 +121,15 @@ func BeaconCommittee(
//
// Spec pseudocode definition:
// def compute_committee(indices: Sequence[ValidatorIndex],
// seed: Hash,
// seed: Bytes32,
// index: uint64,
// count: uint64) -> Sequence[ValidatorIndex]:
// """
// Return the committee corresponding to ``indices``, ``seed``, ``index``, and committee ``count``.
// """
// start = (len(indices) * index) // count
// end = (len(indices) * (index + 1)) // count
// return [indices[compute_shuffled_index(ValidatorIndex(i), len(indices), seed)] for i in range(start, end)
// end = (len(indices) * uint64(index + 1)) // count
// return [indices[compute_shuffled_index(uint64(i), uint64(len(indices)), seed)] for i in range(start, end)]
func ComputeCommittee(
indices []types.ValidatorIndex,
seed [32]byte,
Expand Down
2 changes: 2 additions & 0 deletions beacon-chain/core/helpers/rewards_penalties.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
// """
// Return the combined effective balance of the ``indices``.
// ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero.
// Math safe up to ~10B ETH, afterwhich this overflows uint64.
// """
// return Gwei(max(EFFECTIVE_BALANCE_INCREMENT, sum([state.validators[index].effective_balance for index in indices])))
func TotalBalance(state iface.ReadOnlyValidators, indices []types.ValidatorIndex) uint64 {
Expand Down Expand Up @@ -42,6 +43,7 @@ func TotalBalance(state iface.ReadOnlyValidators, indices []types.ValidatorIndex
// def get_total_active_balance(state: BeaconState) -> Gwei:
// """
// Return the combined effective balance of the active validators.
// Note: ``get_total_balance`` returns ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero.
// """
// return get_total_balance(state, set(get_active_validator_indices(state, get_current_epoch(state))))
func TotalActiveBalance(state iface.ReadOnlyBeaconState) (uint64, error) {
Expand Down
4 changes: 2 additions & 2 deletions beacon-chain/core/helpers/slot_epoch.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const MaxSlotBuffer = uint64(1 << 7)
// Spec pseudocode definition:
// def compute_epoch_at_slot(slot: Slot) -> Epoch:
// """
// Return the epoch number of ``slot``.
// Return the epoch number at ``slot``.
// """
// return Epoch(slot // SLOTS_PER_EPOCH)
func SlotToEpoch(slot types.Slot) types.Epoch {
Expand All @@ -36,7 +36,7 @@ func SlotToEpoch(slot types.Slot) types.Epoch {
// """
// Return the current epoch.
// """
// return compute_epoch_of_slot(state.slot)
// return compute_epoch_at_slot(state.slot)
func CurrentEpoch(state iface.ReadOnlyBeaconState) types.Epoch {
return SlotToEpoch(state.Slot())
}
Expand Down
4 changes: 2 additions & 2 deletions beacon-chain/core/helpers/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ func ActivationExitEpoch(epoch types.Epoch) types.Epoch {
// Return the validator churn limit for the current epoch.
// """
// active_validator_indices = get_active_validator_indices(state, get_current_epoch(state))
// return max(MIN_PER_EPOCH_CHURN_LIMIT, len(active_validator_indices) // CHURN_LIMIT_QUOTIENT)
// return max(MIN_PER_EPOCH_CHURN_LIMIT, uint64(len(active_validator_indices)) // CHURN_LIMIT_QUOTIENT)
func ValidatorChurnLimit(activeValidatorCount uint64) (uint64, error) {
churnLimit := activeValidatorCount / params.BeaconConfig().ChurnLimitQuotient
if churnLimit < params.BeaconConfig().MinPerEpochChurnLimit {
Expand All @@ -173,7 +173,7 @@ func ValidatorChurnLimit(activeValidatorCount uint64) (uint64, error) {
// Return the beacon proposer index at the current slot.
// """
// epoch = get_current_epoch(state)
// seed = hash(get_seed(state, epoch, DOMAIN_BEACON_PROPOSER) + int_to_bytes(state.slot, length=8))
// seed = hash(get_seed(state, epoch, DOMAIN_BEACON_PROPOSER) + uint_to_bytes(state.slot))
// indices = get_active_validator_indices(state, epoch)
// return compute_proposer_index(state, indices, seed)
func BeaconProposerIndex(state iface.ReadOnlyBeaconState) (types.ValidatorIndex, error) {
Expand Down
9 changes: 3 additions & 6 deletions beacon-chain/core/state/transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,9 @@ func ExecuteStateTransition(
// # Cache state root
// previous_state_root = hash_tree_root(state)
// state.state_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_state_root
//
// # Cache latest block header state root
// if state.latest_block_header.state_root == Bytes32():
// state.latest_block_header.state_root = previous_state_root
//
// # Cache block root
// previous_block_root = hash_tree_root(state.latest_block_header)
// state.block_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_block_root
Expand Down Expand Up @@ -192,14 +190,13 @@ func ProcessSlotsUsingNextSlotCache(
//
// Spec pseudocode definition:
// def process_slots(state: BeaconState, slot: Slot) -> None:
// assert state.slot <= slot
// assert state.slot < slot
// while state.slot < slot:
// process_slot(state)
// # Process epoch on the first slot of the next epoch
// # Process epoch on the start slot of the next epoch
// if (state.slot + 1) % SLOTS_PER_EPOCH == 0:
// process_epoch(state)
// state.slot += 1
// ]
// state.slot = Slot(state.slot + 1)
func ProcessSlots(ctx context.Context, state iface.BeaconState, slot types.Slot) (iface.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "core.state.ProcessSlots")
defer span.End()
Expand Down
43 changes: 18 additions & 25 deletions shared/attestationutil/attestation_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,18 @@ func AttestingIndices(bf bitfield.Bitfield, committee []types.ValidatorIndex) ([
//
// Spec pseudocode definition:
// def is_valid_indexed_attestation(state: BeaconState, indexed_attestation: IndexedAttestation) -> bool:
// """
// Check if ``indexed_attestation`` has sorted and unique indices and a valid aggregate signature.
// """
// # Verify indices are sorted and unique
// indices = indexed_attestation.attesting_indices
// if not indices == sorted(set(indices)):
// """
// Check if ``indexed_attestation`` is not empty, has sorted and unique indices and has a valid aggregate signature.
// """
// # Verify indices are sorted and unique
// indices = indexed_attestation.attesting_indices
// if len(indices) == 0 or not indices == sorted(set(indices)):
// return False
// # Verify aggregate signature
// pubkeys = [state.validators[i].pubkey for i in indices]
// domain = get_domain(state, DOMAIN_BEACON_ATTESTER, indexed_attestation.data.target.epoch)
// signing_root = compute_signing_root(indexed_attestation.data, domain)
// return bls.FastAggregateVerify(pubkeys, signing_root, indexed_attestation.signature)
// # Verify aggregate signature
// pubkeys = [state.validators[i].pubkey for i in indices]
// domain = get_domain(state, DOMAIN_BEACON_ATTESTER, indexed_attestation.data.target.epoch)
// signing_root = compute_signing_root(indexed_attestation.data, domain)
// return bls.FastAggregateVerify(pubkeys, signing_root, indexed_attestation.signature)
func VerifyIndexedAttestationSig(ctx context.Context, indexedAtt *ethpb.IndexedAttestation, pubKeys []bls.PublicKey, domain []byte) error {
ctx, span := trace.StartSpan(ctx, "attestationutil.VerifyIndexedAttestationSig")
defer span.End()
Expand Down Expand Up @@ -128,24 +128,17 @@ func VerifyIndexedAttestationSig(ctx context.Context, indexedAtt *ethpb.IndexedA
// Spec pseudocode definition:
// def is_valid_indexed_attestation(state: BeaconState, indexed_attestation: IndexedAttestation) -> bool:
// """
// Check if ``indexed_attestation``is not empty, has valid indices, and signature.
// Check if ``indexed_attestation`` is not empty, has sorted and unique indices and has a valid aggregate signature.
// """
// # Verify indices are sorted and unique
// indices = indexed_attestation.attesting_indices
//
// # Verify max number of indices
// if not len(indices) <= MAX_VALIDATORS_PER_COMMITTEE:
// if len(indices) == 0 or not indices == sorted(set(indices)):
// return False
// # Verify indices are sorted and unique
// if not indices == sorted(set(indices)):
// # Verify aggregate signature
// if not bls_verify(
// pubkey=bls_aggregate_pubkeys([state.validators[i].pubkey for i in indices]),
// message_hash=hash_tree_root(indexed_attestation.data),
// signature=indexed_attestation.signature,
// domain=get_domain(state, DOMAIN_BEACON_ATTESTER, indexed_attestation.data.target.epoch),
// ):
// return False
// return True
// pubkeys = [state.validators[i].pubkey for i in indices]
// domain = get_domain(state, DOMAIN_BEACON_ATTESTER, indexed_attestation.data.target.epoch)
// signing_root = compute_signing_root(indexed_attestation.data, domain)
// return bls.FastAggregateVerify(pubkeys, signing_root, indexed_attestation.signature)
func IsValidAttestationIndices(ctx context.Context, indexedAttestation *ethpb.IndexedAttestation) error {
ctx, span := trace.StartSpan(ctx, "attestationutil.IsValidAttestationIndices")
defer span.End()
Expand Down
2 changes: 1 addition & 1 deletion shared/depositutil/deposit.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
// - Let amount be the amount in Gwei to be deposited by the validator where MIN_DEPOSIT_AMOUNT <= amount <= MAX_EFFECTIVE_BALANCE.
// - Set deposit_data.amount = amount.
// - Let signature be the result of bls_sign of the signing_root(deposit_data) with domain=compute_domain(DOMAIN_DEPOSIT). (Deposits are valid regardless of fork version, compute_domain will default to zeroes there).
// - Send a transaction on the Ethereum 1.0 chain to DEPOSIT_CONTRACT_ADDRESS executing def deposit(pubkey: bytes[48], withdrawal_credentials: bytes[32], signature: bytes[96]) along with a deposit of amount Gwei.
// - Send a transaction on the Ethereum 1.0 chain to DEPOSIT_CONTRACT_ADDRESS executing `deposit(pubkey: bytes[48], withdrawal_credentials: bytes[32], signature: bytes[96])` along with a deposit of amount Gwei.
//
// See: https://github.com/ethereum/eth2.0-specs/blob/master/specs/validator/0_beacon-chain-validator.md#submit-deposit
func DepositInput(depositKey, withdrawalKey bls.SecretKey, amountInGwei uint64) (*ethpb.Deposit_Data, [32]byte, error) {
Expand Down

0 comments on commit cc9bec7

Please sign in to comment.