blocks

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 22, 2019 License: GPL-3.0 Imports: 23 Imported by: 71

Documentation

Overview

Package blocks contains block processing libraries. These libraries process and verify block specific messages such as PoW receipt root, RANDAO, validator deposits, exits and slashing proofs.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ClearEth1DataVoteCache

func ClearEth1DataVoteCache()

ClearEth1DataVoteCache clears the eth1 data vote count cache.

func ConvertToIndexed

func ConvertToIndexed(ctx context.Context, state *pb.BeaconState, attestation *ethpb.Attestation) (*ethpb.IndexedAttestation, error)

ConvertToIndexed converts attestation to (almost) indexed-verifiable form.

Spec pseudocode definition:

def get_indexed_attestation(state: BeaconState, attestation: Attestation) -> IndexedAttestation:
 """
 Return the indexed attestation corresponding to ``attestation``.
 """
 attesting_indices = get_attesting_indices(state, attestation.data, attestation.aggregation_bits)
 custody_bit_1_indices = get_attesting_indices(state, attestation.data, attestation.custody_bits)
 assert custody_bit_1_indices.issubset(attesting_indices)
 custody_bit_0_indices = attesting_indices.difference(custody_bit_1_indices)

 return IndexedAttestation(
     custody_bit_0_indices=sorted(custody_bit_0_indices),
     custody_bit_1_indices=sorted(custody_bit_1_indices),
     data=attestation.data,
     signature=attestation.signature,
 )

func Eth1DataHasEnoughSupport

func Eth1DataHasEnoughSupport(beaconState *pb.BeaconState, data *ethpb.Eth1Data) (bool, error)

Eth1DataHasEnoughSupport returns true when the given eth1data has more than 50% votes in the eth1 voting period. A vote is cast by including eth1data in a block and part of state processing appends eth1data to the state in the Eth1DataVotes list. Iterating through this list checks the votes to see if they match the eth1data.

func IsSlashableAttestationData

func IsSlashableAttestationData(data1 *ethpb.AttestationData, data2 *ethpb.AttestationData) bool

IsSlashableAttestationData verifies a slashing against the Casper Proof of Stake FFG rules.

Spec pseudocode definition:

def is_slashable_attestation_data(data_1: AttestationData, data_2: AttestationData) -> bool:
 """
 Check if ``data_1`` and ``data_2`` are slashable according to Casper FFG rules.
 """
 return (
     # Double vote
     (data_1 != data_2 and data_1.target.epoch == data_2.target.epoch) or
     # Surround vote
     (data_1.source.epoch < data_2.source.epoch and data_2.target.epoch < data_1.target.epoch)
 )

func NewGenesisBlock

func NewGenesisBlock(stateRoot []byte) *ethpb.BeaconBlock

NewGenesisBlock returns the canonical, genesis block for the beacon chain protocol.

func ProcessAttestation

func ProcessAttestation(ctx context.Context, beaconState *pb.BeaconState, att *ethpb.Attestation) (*pb.BeaconState, error)

ProcessAttestation verifies an input attestation can pass through processing using the given beacon state.

Spec pseudocode definition:

def process_attestation(state: BeaconState, attestation: Attestation) -> None:
  """
  Process ``Attestation`` operation.
  """
  data = attestation.data
  assert data.crosslink.shard < SHARD_COUNT
  assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state))

  attestation_slot = get_attestation_data_slot(state, data)
  assert attestation_slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= attestation_slot + SLOTS_PER_EPOCH

  committee = get_crosslink_committee(state, data.target.epoch, data.crosslink.shard)
  assert len(attestation.aggregation_bits) == len(attestation.custody_bits) == len(committee)

  pending_attestation = PendingAttestation(
      data=data,
      aggregation_bitfield=attestation.aggregation_bitfield,
      inclusion_delay=state.slot - attestation_slot,
      proposer_index=get_beacon_proposer_index(state),
  )

  if data.target_epoch == get_current_epoch(state):
    assert data.source == state.current_justified_checkpoint
    parent_crosslink = state.current_crosslinks[data.crosslink.shard]
    state.current_epoch_attestations.append(pending_attestation)
  else:
    assert data.source == state.previous_justified_checkpoint
    parent_crosslink = state.previous_crosslinks[data.crosslink.shard]
    state.previous_epoch_attestations.append(pending_attestation)

  # Check crosslink against expected parent crosslink
  assert data.crosslink.parent_root == hash_tree_root(parent_crosslink)
  assert data.crosslink.start_epoch == parent_crosslink.end_epoch
  assert data.crosslink.end_epoch == min(data.target.epoch, parent_crosslink.end_epoch + MAX_EPOCHS_PER_CROSSLINK)
  assert data.crosslink.data_root == Bytes32()  # [to be removed in phase 1]

  # Check signature
  assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation))

func ProcessAttestationNoVerify

func ProcessAttestationNoVerify(ctx context.Context, beaconState *pb.BeaconState, att *ethpb.Attestation) (*pb.BeaconState, error)

ProcessAttestationNoVerify processes the attestation without verifying the attestation signature. This method is used to validate attestations whose signatures have already been verified.

func ProcessAttestations

func ProcessAttestations(ctx context.Context, beaconState *pb.BeaconState, body *ethpb.BeaconBlockBody) (*pb.BeaconState, error)

ProcessAttestations applies processing operations to a block's inner attestation records. This function returns a list of pending attestations which can then be appended to the BeaconState's latest attestations.

func ProcessAttestationsNoVerify

func ProcessAttestationsNoVerify(ctx context.Context, beaconState *pb.BeaconState, body *ethpb.BeaconBlockBody) (*pb.BeaconState, error)

ProcessAttestationsNoVerify applies processing operations to a block's inner attestation records. The only difference would be that the attestation signature would not be verified.

func ProcessAttesterSlashings

func ProcessAttesterSlashings(ctx context.Context, beaconState *pb.BeaconState, body *ethpb.BeaconBlockBody) (*pb.BeaconState, error)

ProcessAttesterSlashings is one of the operations performed on each processed beacon block to slash attesters based on Casper FFG slashing conditions if any slashable events occurred.

Spec pseudocode definition:

def process_attester_slashing(state: BeaconState, attester_slashing: AttesterSlashing) -> None:
 """
 Process ``AttesterSlashing`` operation.
 """
 attestation_1 = attester_slashing.attestation_1
 attestation_2 = attester_slashing.attestation_2
 assert is_slashable_attestation_data(attestation_1.data, attestation_2.data)
 validate_indexed_attestation(state, attestation_1)
 validate_indexed_attestation(state, attestation_2)

 slashed_any = False
 attesting_indices_1 = attestation_1.custody_bit_0_indices + attestation_1.custody_bit_1_indices
 attesting_indices_2 = attestation_2.custody_bit_0_indices + attestation_2.custody_bit_1_indices
 for index in sorted(set(attesting_indices_1).intersection(attesting_indices_2)):
     if is_slashable_validator(state.validators[index], get_current_epoch(state)):
         slash_validator(state, index)
         slashed_any = True
 assert slashed_any

func ProcessBlockHeader

func ProcessBlockHeader(
	beaconState *pb.BeaconState,
	block *ethpb.BeaconBlock,
) (*pb.BeaconState, error)

ProcessBlockHeader validates a block by its header.

Spec pseudocode definition:

 def process_block_header(state: BeaconState, block: BeaconBlock) -> None:
   # Verify that the slots match
   assert block.slot == state.slot
   # Verify that the parent matches
   assert block.parent_root == signing_root(state.latest_block_header)
   # Save current block as the new latest block
   state.latest_block_header = BeaconBlockHeader(
       slot=block.slot,
       parent_root=block.parent_root,
       # state_root: zeroed, 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)]
   assert not proposer.slashed
   # Verify proposer signature
   assert bls_verify(proposer.pubkey, signing_root(block), block.signature, get_domain(state, DOMAIN_BEACON_PROPOSER))

func ProcessBlockHeaderNoVerify

func ProcessBlockHeaderNoVerify(
	beaconState *pb.BeaconState,
	block *ethpb.BeaconBlock,
) (*pb.BeaconState, error)

ProcessBlockHeaderNoVerify validates a block by its header but skips proposer signature verification.

WARNING: This method does not verify proposer signature. This is used for proposer to compute state root using a unsigned block.

Spec pseudocode definition:

 def process_block_header(state: BeaconState, block: BeaconBlock) -> None:
   # Verify that the slots match
   assert block.slot == state.slot
   # Verify that the parent matches
   assert block.parent_root == signing_root(state.latest_block_header)
   # Save current block as the new latest block
   state.latest_block_header = BeaconBlockHeader(
       slot=block.slot,
       parent_root=block.parent_root,
       # state_root: zeroed, 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)]
   assert not proposer.slashed

func ProcessDeposit

func ProcessDeposit(beaconState *pb.BeaconState, deposit *ethpb.Deposit, valIndexMap map[[48]byte]int) (*pb.BeaconState, error)

ProcessDeposit takes in a deposit object and inserts it into the registry as a new validator or balance change.

Spec pseudocode definition:

def process_deposit(state: BeaconState, deposit: Deposit) -> None:
  """
  Process an Eth1 deposit, registering a validator or increasing its balance.
  """
  # Verify the Merkle branch
  assert verify_merkle_branch(
      leaf=hash_tree_root(deposit.data),
      proof=deposit.proof,
      depth=DEPOSIT_CONTRACT_TREE_DEPTH,
      index=deposit.index,
      root=state.latest_eth1_data.deposit_root,
  )

  # Deposits must be processed in order
  assert deposit.index == state.deposit_index
  state.deposit_index += 1

  pubkey = deposit.data.pubkey
  amount = deposit.data.amount
  validator_pubkeys = [v.pubkey for v in state.validator_registry]
  if pubkey not in validator_pubkeys:
      # Verify the deposit signature (proof of possession).
      # Invalid signatures are allowed by the deposit contract, and hence included on-chain, but must not be processed.
      if not bls_verify(pubkey, signing_root(deposit.data), deposit.data.signature%d, get_domain(state, DOMAIN_DEPOSIT)):
          return

      # Add validator and balance entries
      state.validator_registry.append(Validator(
          pubkey=pubkey,
          withdrawal_credentials=deposit.data.withdrawal_credentials,
          activation_eligibility_epoch=FAR_FUTURE_EPOCH,
          activation_epoch=FAR_FUTURE_EPOCH,
          exit_epoch=FAR_FUTURE_EPOCH,
          withdrawable_epoch=FAR_FUTURE_EPOCH,
          effective_balance=min(amount - amount % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
      ))
      state.balances.append(amount)
  else:
      # Increase balance by deposit amount
      index = validator_pubkeys.index(pubkey)
      increase_balance(state, index, amount)

func ProcessDeposits

func ProcessDeposits(ctx context.Context, beaconState *pb.BeaconState, body *ethpb.BeaconBlockBody) (*pb.BeaconState, error)

ProcessDeposits is one of the operations performed on each processed beacon block to verify queued validators from the Ethereum 1.0 Deposit Contract into the beacon chain.

Spec pseudocode definition:

For each deposit in block.body.deposits:
  process_deposit(state, deposit)

func ProcessEth1DataInBlock

func ProcessEth1DataInBlock(beaconState *pb.BeaconState, block *ethpb.BeaconBlock) (*pb.BeaconState, error)

ProcessEth1DataInBlock is an operation performed on each beacon block to ensure the ETH1 data votes are processed into the beacon state.

Official spec definition:

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 > SLOTS_PER_ETH1_VOTING_PERIOD:
     state.latest_eth1_data = body.eth1_data

func ProcessProposerSlashings

func ProcessProposerSlashings(ctx context.Context, beaconState *pb.BeaconState, body *ethpb.BeaconBlockBody) (*pb.BeaconState, error)

ProcessProposerSlashings is one of the operations performed on each processed beacon block to slash proposers based on slashing conditions if any slashable events occurred.

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 that the epoch is the same
 assert slot_to_epoch(proposer_slashing.header_1.slot) == slot_to_epoch(proposer_slashing.header_2.slot)
 # But the headers are different
 assert proposer_slashing.header_1 != proposer_slashing.header_2
 # Check proposer is slashable
 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)

 slash_validator(state, proposer_slashing.proposer_index)

func ProcessRandao

func ProcessRandao(
	beaconState *pb.BeaconState,
	body *ethpb.BeaconBlockBody,
) (*pb.BeaconState, error)

ProcessRandao checks the block proposer's randao commitment and generates a new randao mix to update in the beacon state's latest randao mixes slice.

Spec pseudocode definition:

def process_randao(state: BeaconState, body: BeaconBlockBody) -> None:
  proposer = state.validator_registry[get_beacon_proposer_index(state)]
  # Verify that the provided randao value is valid
  assert bls_verify(
      proposer.pubkey,
      hash_tree_root(get_current_epoch(state)),
      body.randao_reveal,
      get_domain(state, DOMAIN_RANDAO),
  )
  # Mix it in
  state.latest_randao_mixes[get_current_epoch(state) % LATEST_RANDAO_MIXES_LENGTH] = (
      xor(get_randao_mix(state, get_current_epoch(state)),
          hash(body.randao_reveal))
  )

func ProcessRandaoNoVerify

func ProcessRandaoNoVerify(
	beaconState *pb.BeaconState,
	body *ethpb.BeaconBlockBody,
) (*pb.BeaconState, error)

ProcessRandaoNoVerify generates a new randao mix to update in the beacon state's latest randao mixes slice.

Spec pseudocode definition:

# Mix it in
state.latest_randao_mixes[get_current_epoch(state) % LATEST_RANDAO_MIXES_LENGTH] = (
    xor(get_randao_mix(state, get_current_epoch(state)),
        hash(body.randao_reveal))
)

func ProcessTransfers

func ProcessTransfers(
	beaconState *pb.BeaconState,
	body *ethpb.BeaconBlockBody,
) (*pb.BeaconState, error)

ProcessTransfers is one of the operations performed on each processed beacon block to determine transfers between beacon chain balances.

Spec pseudocode definition:

  def process_transfer(state: BeaconState, transfer: Transfer) -> None:
   """
   Process ``Transfer`` operation.
   """
   # Verify the balance the covers amount and fee (with overflow protection)
	  assert state.balances[transfer.sender] >= max(transfer.amount + transfer.fee, transfer.amount, transfer.fee)
   # A transfer is valid in only one slot
   assert state.slot == transfer.slot
   # SenderIndex must satisfy at least one of the following conditions in the parenthesis:
   assert (
		  # * Has not been activated
       state.validator_registry[transfer.sender].activation_eligibility_epoch == FAR_FUTURE_EPOCH or
       # * Is withdrawable
       get_current_epoch(state) >= state.validator_registry[transfer.sender].withdrawable_epoch or
       # * Balance after transfer is more than the effective balance threshold
       transfer.amount + transfer.fee + MAX_EFFECTIVE_BALANCE <= state.balances[transfer.sender]
   )
   # Verify that the pubkey is valid
   assert (
       state.validator_registry[transfer.sender].withdrawal_credentials ==
       int_to_bytes(BLS_WITHDRAWAL_PREFIX, length=1) + hash(transfer.pubkey)[1:]
   )
   # Verify that the signature is valid
   assert bls_verify(transfer.pubkey, signing_root(transfer), transfer.signature, get_domain(state, DOMAIN_TRANSFER))
   # Process the transfer
   decrease_balance(state, transfer.sender, transfer.amount + transfer.fee)
   increase_balance(state, transfer.recipient, transfer.amount)
   increase_balance(state, get_beacon_proposer_index(state), transfer.fee)
   # Verify balances are not dust
   assert not (0 < state.balances[transfer.sender] < MIN_DEPOSIT_AMOUNT)
   assert not (0 < state.balances[transfer.recipient] < MIN_DEPOSIT_AMOUNT)

func ProcessVoluntaryExits

func ProcessVoluntaryExits(ctx context.Context, beaconState *pb.BeaconState, body *ethpb.BeaconBlockBody) (*pb.BeaconState, error)

ProcessVoluntaryExits is one of the operations performed on each processed beacon block to determine which validators should exit the state's validator registry.

Spec pseudocode definition:

def process_voluntary_exit(state: BeaconState, exit: VoluntaryExit) -> None:
 """
 Process ``VoluntaryExit`` operation.
 """
 validator = state.validator_registry[exit.validator_index]
 # Verify the validator is active
 assert is_active_validator(validator, get_current_epoch(state))
 # Verify the validator has not yet exited
 assert validator.exit_epoch == FAR_FUTURE_EPOCH
 # Exits must specify an epoch when they become valid; they are not valid before then
 assert get_current_epoch(state) >= exit.epoch
 # Verify the validator has been active long enough
 assert get_current_epoch(state) >= validator.activation_epoch + PERSISTENT_COMMITTEE_PERIOD
 # Verify signature
 domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, exit.epoch)
 assert bls_verify(validator.pubkey, signing_root(exit), exit.signature, domain)
 # Initiate exit
 initiate_validator_exit(state, exit.validator_index)

func ProcessVoluntaryExitsNoVerify

func ProcessVoluntaryExitsNoVerify(
	beaconState *pb.BeaconState,
	body *ethpb.BeaconBlockBody,
) (*pb.BeaconState, error)

ProcessVoluntaryExitsNoVerify processes all the voluntary exits in a block body, without verifying their BLS signatures.

func VerifyAttestation

func VerifyAttestation(ctx context.Context, beaconState *pb.BeaconState, att *ethpb.Attestation) error

VerifyAttestation converts and attestation into an indexed attestation and verifies the signature in that attestation.

func VerifyAttesterSlashing

func VerifyAttesterSlashing(ctx context.Context, beaconState *pb.BeaconState, slashing *ethpb.AttesterSlashing) error

VerifyAttesterSlashing validates the attestation data in both attestations in the slashing object.

func VerifyExit

func VerifyExit(beaconState *pb.BeaconState, exit *ethpb.VoluntaryExit) error

VerifyExit implements the spec defined validation for voluntary exits.

Spec pseudocode definition:

def process_voluntary_exit(state: BeaconState, exit: VoluntaryExit) -> None:
 """
 Process ``VoluntaryExit`` operation.
 """
 validator = state.validator_registry[exit.validator_index]
 # Verify the validator is active
 assert is_active_validator(validator, get_current_epoch(state))
 # Verify the validator has not yet exited
 assert validator.exit_epoch == FAR_FUTURE_EPOCH
 # Exits must specify an epoch when they become valid; they are not valid before then
 assert get_current_epoch(state) >= exit.epoch
 # Verify the validator has been active long enough
 assert get_current_epoch(state) >= validator.activation_epoch + PERSISTENT_COMMITTEE_PERIOD
 # Verify signature
 domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, exit.epoch)
 assert bls_verify(validator.pubkey, signing_root(exit), exit.signature, domain)

func VerifyIndexedAttestation

func VerifyIndexedAttestation(ctx context.Context, beaconState *pb.BeaconState, indexedAtt *ethpb.IndexedAttestation) error

VerifyIndexedAttestation determines the validity of an indexed attestation.

Spec pseudocode definition:

def is_valid_indexed_attestation(state: BeaconState, indexed_attestation: IndexedAttestation) -> bool:
  """
  Check if ``indexed_attestation`` has valid indices and signature.
  """
  bit_0_indices = indexed_attestation.custody_bit_0_indices
  bit_1_indices = indexed_attestation.custody_bit_1_indices

  # Verify no index has custody bit equal to 1 [to be removed in phase 1]
  if not len(bit_1_indices) == 0:
      return False
  # Verify max number of indices
  if not len(bit_0_indices) + len(bit_1_indices) <= MAX_VALIDATORS_PER_COMMITTEE:
      return False
  # Verify index sets are disjoint
  if not len(set(bit_0_indices).intersection(bit_1_indices)) == 0:
      return False
  # Verify indices are sorted
  if not (bit_0_indices == sorted(bit_0_indices) and bit_1_indices == sorted(bit_1_indices)):
      return False
  # Verify aggregate signature
  if not bls_verify_multiple(
      pubkeys=[
          bls_aggregate_pubkeys([state.validators[i].pubkey for i in bit_0_indices]),
          bls_aggregate_pubkeys([state.validators[i].pubkey for i in bit_1_indices]),
      ],
      message_hashes=[
          hash_tree_root(AttestationDataAndCustodyBit(data=indexed_attestation.data, custody_bit=0b0)),
          hash_tree_root(AttestationDataAndCustodyBit(data=indexed_attestation.data, custody_bit=0b1)),
      ],
      signature=indexed_attestation.signature,
      domain=get_domain(state, DOMAIN_ATTESTATION, indexed_attestation.data.target.epoch),
  ):
      return False
  return True

func VerifyProposerSlashing

func VerifyProposerSlashing(
	beaconState *pb.BeaconState,
	slashing *ethpb.ProposerSlashing,
) error

VerifyProposerSlashing verifies that the data provided fro slashing is valid.

Types

This section is empty.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL