-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from ethereum/align-to-beacon-api
Align to beacon-APIs
- Loading branch information
Showing
3 changed files
with
272 additions
and
97 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,94 @@ | ||
from typing import List | ||
from eth2spec.phase0.mainnet import ( | ||
Container, | ||
Slot, | ||
AttestationData, | ||
Attestation, | ||
ValidatorIndex, | ||
Container, SignedBeaconBlock, uint64, Bytes32, | ||
BLSPubkey, BLSSignature, | ||
Slot, Epoch, | ||
ValidatorIndex, CommitteeIndex, | ||
AttestationData, Attestation, | ||
BeaconBlock, SignedBeaconBlock, | ||
) | ||
|
||
class AttestationDuty(Container): | ||
# TODO: Update schema to include committee_index etc. as defined | ||
# in https://ethereum.github.io/beacon-APIs/#/ | ||
pubkey: BLSPubkey | ||
validator_index: ValidatorIndex | ||
committee_index: CommitteeIndex | ||
committee_length: uint64 | ||
committees_at_slot: uint64 | ||
validator_committee_index: ValidatorIndex # TODO: Is this the correct datatype? | ||
slot: Slot | ||
validator_index: ValidatorIndex | ||
|
||
class ProposerDuty(Container): | ||
pubkey: BLSPubkey | ||
validator_index: ValidatorIndex | ||
slot: Slot | ||
|
||
|
||
# Beacon Node Interface | ||
|
||
# Beacon Node | ||
def bn_get_next_attestation_duty() -> AttestationDuty: | ||
def bn_get_attestation_duties_for_epoch(validator_indices: List[ValidatorIndex], epoch: Epoch) -> List[AttestationDuty]: | ||
# TODO: Define typing here: | ||
# What's the size of validator_indices & the returned attestation_duties? | ||
"""Fetch attestation duties for the validator indices in the epoch. | ||
Uses https://ethereum.github.io/beacon-APIs/#/ValidatorRequiredApi/getAttesterDuties | ||
""" | ||
pass | ||
|
||
def bn_broadcast_attestation(attestation: Attestation) -> None: | ||
def bn_get_attestation_data(slot: Slot, committee_index: CommitteeIndex) -> AttestationData: | ||
"""Produces attestation data for the given slot & committee index. | ||
Uses https://ethereum.github.io/beacon-APIs/#/ValidatorRequiredApi/produceAttestationData | ||
""" | ||
pass | ||
|
||
# Validator Client | ||
def vc_is_slashable(attestation_data: AttestationData, validator_index: ValidatorIndex) -> bool: | ||
# TODO: Should we use validator index or pubkey? | ||
|
||
def bn_submit_attestation(attestation: Attestation) -> None: | ||
"""Submit attestation to BN for p2p gossip. | ||
Uses https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolAttestations | ||
""" | ||
pass | ||
|
||
def bn_get_proposer_duties_for_epoch(epoch: Epoch) -> List[ProposerDuty]: | ||
"""Fetch proposer duties for all proposers in the epoch. | ||
Uses https://ethereum.github.io/beacon-APIs/#/ValidatorRequiredApi/getProposerDuties | ||
""" | ||
pass | ||
|
||
def bn_produce_block(slot: Slot, randao_reveal: BLSSignature, graffiti: Bytes32) -> BeaconBlock: | ||
"""Produces valid block for given slot using provided data | ||
Uses https://ethereum.github.io/beacon-APIs/#/ValidatorRequiredApi/produceBlockV2 | ||
""" | ||
pass | ||
|
||
# TODO: What object does the VC sign? | ||
# Is it the same object that the BN accepts for broadcast? | ||
def vc_sign_attestation(attestation_data: AttestationData, validator_index: ValidatorIndex) -> AttestationData: | ||
def bn_submit_block(block: SignedBeaconBlock) -> None: | ||
"""Submit block to BN for p2p gossip. | ||
Uses https://ethereum.github.io/beacon-APIs/#/ValidatorRequiredApi/publishBlock | ||
""" | ||
pass | ||
|
||
|
||
# Validator Client Interface | ||
|
||
def vc_is_slashable_attestation_data(attestation_data: AttestationData, validator_pubkey: BLSPubkey) -> bool: | ||
"""Checks whether the attestation data is slashable according to the anti-slashing database. | ||
This endpoint does not exist in beacon-APIs. | ||
""" | ||
pass | ||
|
||
def vc_sign_attestation(attestation_data: AttestationData, attestation_duty: AttestationDuty) -> Attestation: | ||
"""Returns a signed attestations that is constructed using the given attestation data & attestation duty. | ||
This endpoint does not exist in beacon-APIs. | ||
""" | ||
# See note about attestation construction here: | ||
# https://github.com/ethereum/beacon-APIs/blame/05c1bc142e1a3fb2a63c79098743776241341d08/validator-flow.md#L35-L37 | ||
pass | ||
|
||
def vc_is_slashable_block(block: BeaconBlock, validator_pubkey: BLSPubkey) -> bool: | ||
"""Checks whether the block is slashable according to the anti-slashing database. | ||
This endpoint does not exist in beacon-APIs. | ||
""" | ||
pass | ||
|
||
def vc_sign_block(block: BeaconBlock, proposer_duty: ProposerDuty) -> SignedBeaconBlock: | ||
"""Returns a signed beacon block using the validator index given in the proposer duty. | ||
This endpoint does not exist in beacon-APIs. | ||
""" | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,105 @@ | ||
from test import ( | ||
get_current_time, | ||
bn_get_next_attestation_duty, | ||
bn_broadcast_attestation, | ||
from eth2_node import ( | ||
AttestationDuty, ProposerDuty, | ||
AttestationData, BeaconBlock, | ||
bn_get_attestation_duties_for_epoch, | ||
bn_get_attestation_data, | ||
bn_submit_attestation, | ||
bn_get_proposer_duties_for_epoch, | ||
bn_produce_block, | ||
bn_submit_block, | ||
vc_is_slashable_attestation_data, | ||
vc_sign_attestation, | ||
calculate_attestation_time, | ||
consensus, | ||
) | ||
from eth2spec.phase0.mainnet import ( | ||
Attestation, | ||
vc_is_slashable_block, | ||
vc_sign_block, | ||
) | ||
|
||
def attestation_duty_loop(): | ||
# run in a loop forever | ||
attestation_duty = bn_get_next_attestation_duty() | ||
while get_current_time() < calculate_attestation_time(attestation_duty.slot): | ||
pass | ||
|
||
# Obtain lock on consensus process here - only a single consensus instance | ||
# should be running at any given time | ||
attestation_data = consensus(attestation_duty.slot) | ||
""" | ||
Consensus Specification | ||
""" | ||
|
||
def consensus_is_valid_attestation_data(attestation_data: AttestationData, attestation_duty: AttestationDuty) -> bool: | ||
"""Determines if the given attestation is valid for the attestation duty. | ||
""" | ||
assert attestation_data.slot == attestation_duty.slot | ||
assert attestation_data.committee_index == attestation_duty.committee_index | ||
assert not vc_is_slashable_attestation_data(attestation_data, attestation_duty.pubkey) | ||
|
||
def consensus_on_attestation(attestation_duty: AttestationDuty) -> AttestationData: | ||
"""Consensus protocol between distributed validator nodes for attestation values. | ||
Returns the decided value. | ||
The consensus protocol must use `consensus_is_valid_attestation_data` to determine | ||
validity of the proposed attestation value. | ||
""" | ||
pass | ||
|
||
def consensus_is_valid_block(block: BeaconBlock, proposer_duty: ProposerDuty) -> bool: | ||
"""Determines if the given block is valid for the proposer duty. | ||
""" | ||
assert block.slot == proposer_duty.slot | ||
# TODO: Assert correct block.proposer_index | ||
assert not vc_is_slashable_block(block, proposer_duty.pubkey) | ||
|
||
def consensus_on_block(proposer_duty: ProposerDuty) -> AttestationData: | ||
"""Consensus protocol between distributed validator nodes for block values. | ||
Returns the decided value. | ||
The consensus protocol must use `consensus_is_valid_block` to determine | ||
validity of the proposed block value. | ||
""" | ||
pass | ||
|
||
|
||
""" | ||
Attestation Production Process: | ||
1. At the start of every epoch, get attestation duties for epoch+1 by running | ||
bn_get_attestation_duties_for_epoch(validator_indices, epoch+1) | ||
2. For each attestation_duty recevied in Step 1, schedule | ||
serve_attestation_duty(attestation_duty) at 1/3rd way through the slot | ||
attestation_duty.slot | ||
See notes here: | ||
https://github.com/ethereum/beacon-APIs/blob/05c1bc142e1a3fb2a63c79098743776241341d08/validator-flow.md#attestation | ||
""" | ||
|
||
def serve_attestation_duty(attestation_duty): | ||
# Obtain lock on consensus_on_attestation here. | ||
# Only a single consensus_on_attestation instance should be | ||
# running at any given time | ||
attestation_data = consensus_on_attestation(attestation_duty) | ||
|
||
# 1. Threshold sign attestation from local VC | ||
threshold_signed_attestation_data = vc_sign_attestation(attestation_data, attestation_duty.validator_index) | ||
threshold_signed_attestation = vc_sign_attestation(attestation_data, attestation_duty) | ||
# 2. Broadcast threshold signed attestation | ||
# TODO | ||
# 3. Reconstruct complete signed attestation by combining threshold signed attestations | ||
complete_signed_attestation_data = threshold_signed_attestation_data | ||
complete_signed_attestation = Attestation(data=complete_signed_attestation_data) | ||
complete_signed_attestation = threshold_signed_attestation | ||
# 4. Send complete signed attestation to BN for broadcast | ||
bn_broadcast_attestation(complete_signed_attestation) | ||
bn_submit_attestation(complete_signed_attestation) | ||
|
||
# Release lock on consensus_on_attestation here. | ||
|
||
""" | ||
Block Production Process: | ||
1. At the start of every epoch, get proposer duties for epoch+1 by running | ||
bn_get_proposer_duties_for_epoch(epoch+1) | ||
2. For each proposer_duty recevied in Step 1 for our validators, schedule | ||
serve_proposer_duty(proposer_duty) at beginning of slot proposer_duty.slot | ||
See notes here: | ||
https://github.com/ethereum/beacon-APIs/blob/05c1bc142e1a3fb2a63c79098743776241341d08/validator-flow.md#block-proposing | ||
""" | ||
|
||
# Release lock on consensus process here | ||
def serve_proposer_duty(proposer_duty): | ||
# Obtain lock on consensus_on_block here. | ||
# Only a single consensus_on_block instance should be | ||
# running at any given time | ||
block = consensus_on_block(proposer_duty) | ||
|
||
print( | ||
f"Duty Slot: {attestation_duty.slot}, Attestation Slot: {attestation_data.slot}") | ||
# 1. Threshold sign block from local VC | ||
threshold_signed_block = vc_sign_block(block, proposer_duty) | ||
# 2. Broadcast threshold signed block | ||
# 3. Reconstruct complete signed block by combining threshold signed blocks | ||
complete_signed_block = threshold_signed_block | ||
# 4. Send complete signed block to BN for broadcast | ||
bn_submit_block(complete_signed_block) | ||
|
||
while True: | ||
attestation_duty_loop() | ||
# Release lock on consensus_on_block here. |
Oops, something went wrong.