From 086df84bdc6805d1c0ad1e1c4ff953fa1bd3802b Mon Sep 17 00:00:00 2001 From: vbuterin Date: Thu, 7 Feb 2019 19:34:54 -0600 Subject: [PATCH 1/3] Attestation data contains latest crosslink, not just latest crosslink data The reason to do this is that it makes it calculable from inside an attestation how many epochs the attestation spans over, which is needed for proof of custody reasons. It's a relatively small change and so arguably easier to do now than to do as a patch in phase 1. Note that this changes the meaning of latest_crosslink.epoch, from the epoch when the latest crosslink was included to the epoch that the latest crosslink was for. This affects the line: * `state.latest_crosslinks[shard].epoch > state.validator_registry_update_epoch` for every shard number `shard` in `[(state.current_epoch_start_shard + i) % SHARD_COUNT for i in range(get_current_epoch_committee_count(state))]` (that is, for every shard in the current committees) But this may actually make it _more_ correct, as it means that in the case where >512 shards are processed per epoch, and so a committee from the previous epoch could get finalized in the current epoch, that would no longer count toward every shard having received a "new" crosslink. --- specs/core/0_beacon-chain.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index f9c155c53..b98bdf3b8 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -362,8 +362,8 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git 'epoch_boundary_root': 'bytes32', # Shard block's hash of root 'shard_block_root': 'bytes32', - # Last crosslink's hash of root - 'latest_crosslink_root': 'bytes32', + # Last crosslink + 'latest_crosslink': Crosslink, # Last justified epoch in the beacon state 'justified_epoch': 'uint64', # Hash of the last justified beacon block @@ -1688,7 +1688,7 @@ For each `attestation` in `block.body.attestations`: * Verify that `attestation.data.slot <= state.slot - MIN_ATTESTATION_INCLUSION_DELAY < attestation.data.slot + EPOCH_LENGTH`. * Verify that `attestation.data.justified_epoch` is equal to `state.justified_epoch if attestation.data.slot >= get_epoch_start_slot(get_current_epoch(state)) else state.previous_justified_epoch`. * Verify that `attestation.data.justified_block_root` is equal to `get_block_root(state, get_epoch_start_slot(attestation.data.justified_epoch))`. -* Verify that either `attestation.data.latest_crosslink_root` or `attestation.data.shard_block_root` equals `state.latest_crosslinks[attestation.data.shard].shard_block_root`. +* Verify that either (i) `state.latest_crosslinks[attestation.data.shard] == attestation.data.latest_crosslink` or (ii) `state.latest_crosslinks[attestation.data.shard] == Crosslink(shard_block_root=attestation.data.shard_block_root, epoch=slot_to_epoch(attestation.data.slot))` * Verify bitfields and aggregate signature: ```python @@ -1860,7 +1860,7 @@ Finally, update the following: For every `slot in range(get_epoch_start_slot(previous_epoch), get_epoch_start_slot(next_epoch))`, let `crosslink_committees_at_slot = get_crosslink_committees_at_slot(state, slot)`. For every `(crosslink_committee, shard)` in `crosslink_committees_at_slot`, compute: -* Set `state.latest_crosslinks[shard] = Crosslink(epoch=current_epoch, shard_block_root=winning_root(crosslink_committee))` if `3 * total_attesting_balance(crosslink_committee) >= 2 * get_total_balance(crosslink_committee)`. +* Set `state.latest_crosslinks[shard] = Crosslink(epoch=slot_to_epoch(slot), shard_block_root=winning_root(crosslink_committee))` if `3 * total_attesting_balance(crosslink_committee) >= 2 * get_total_balance(crosslink_committee)`. #### Rewards and penalties From f0cbacb828baa6ed454bea5d5efe52b0a73b67f5 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 7 Feb 2019 20:22:28 -0800 Subject: [PATCH 2/3] add missing . --- specs/core/0_beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index b98bdf3b8..f66839349 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1688,7 +1688,7 @@ For each `attestation` in `block.body.attestations`: * Verify that `attestation.data.slot <= state.slot - MIN_ATTESTATION_INCLUSION_DELAY < attestation.data.slot + EPOCH_LENGTH`. * Verify that `attestation.data.justified_epoch` is equal to `state.justified_epoch if attestation.data.slot >= get_epoch_start_slot(get_current_epoch(state)) else state.previous_justified_epoch`. * Verify that `attestation.data.justified_block_root` is equal to `get_block_root(state, get_epoch_start_slot(attestation.data.justified_epoch))`. -* Verify that either (i) `state.latest_crosslinks[attestation.data.shard] == attestation.data.latest_crosslink` or (ii) `state.latest_crosslinks[attestation.data.shard] == Crosslink(shard_block_root=attestation.data.shard_block_root, epoch=slot_to_epoch(attestation.data.slot))` +* Verify that either (i) `state.latest_crosslinks[attestation.data.shard] == attestation.data.latest_crosslink` or (ii) `state.latest_crosslinks[attestation.data.shard] == Crosslink(shard_block_root=attestation.data.shard_block_root, epoch=slot_to_epoch(attestation.data.slot))`. * Verify bitfields and aggregate signature: ```python From 6d9581281dba8c8d2cf127ddd07e6202759c405c Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 7 Feb 2019 21:25:47 -0700 Subject: [PATCH 3/3] change latest_crosslink_root to latest_crosslink in validator guide --- specs/validator/0_beacon-chain-validator.md | 6 +- wire-api.md | 93 +++++++++++++++++++++ 2 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 wire-api.md diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 744df690f..d1246c6fa 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -42,7 +42,7 @@ __NOTICE__: This document is a work-in-progress for researchers and implementers - [Beacon block root](#beacon-block-root) - [Epoch boundary root](#epoch-boundary-root) - [Shard block root](#shard-block-root) - - [Latest crosslink root](#latest-crosslink-root) + - [Latest crosslink](#latest-crosslink) - [Justified epoch](#justified-epoch) - [Justified block root](#justified-block-root) - [Construct attestation](#construct-attestation) @@ -270,9 +270,9 @@ Set `attestation_data.shard_block_root = ZERO_HASH`. _Note:_ This is a stub for phase 0. -##### Latest crosslink root +##### Latest crosslink -Set `attestation_data.latest_crosslink_root = state.latest_crosslinks[shard].shard_block_root` where `state` is the beacon state at `head` and `shard` is the validator's assigned shard. +Set `attestation_data.latest_crosslink = state.latest_crosslinks[shard]` where `state` is the beacon state at `head` and `shard` is the validator's assigned shard. ##### Justified epoch diff --git a/wire-api.md b/wire-api.md new file mode 100644 index 000000000..0eff650bd --- /dev/null +++ b/wire-api.md @@ -0,0 +1,93 @@ +# Phase 0 Wire API [WIP] + +This is the minimal wire API required for Phase 0 of Eth2.0. Note that this is _not_ the wire protocol but the interface right above. Once we settle on the API required, we can specify the underlying protocol. + +All API methods are specified as the plural `list` version, assuming that if singular objects are sent or requested that the input will just be a list of length 1. + +"Bad form" is any action that is not explicitly against the protocol but is not in the best interest of one's peers or the protocol in general. Messages/requests that are considered bad form may reduce the reputation of the sending node and may result in being dropped. + +## Network topology + +Ethereum 2.0 network topology consists of a pubsub mapping of peers to "topics". These topics along with peer mappings effectively form subnets. + +The primary topics of core protocol consideration are: +* `beacon`: All messages for the beacon chain are mapped to topic `beacon`. +* `shard-{number}` for all integers, `number` in `range(SHARD_SUBNET_COUNT)`: Messages for a given shard defined by `shard_number` are mapped to topic `shard-{shard_number % SHARD_SUBNET_COUNT}`. + +We use `discv5` to discover peers of select topics, and we use `gossipsub`, a libp2p routing protocol, to route messages of a particular topic to the subnet in question. + +Note: attempting to broadcast or request messages about a topic not subscribed to by the peer is considered bad form. For example, running `send_attestations(attestations)` where one or more of the attestations have `attestation.data.shard == 5` to a peer not subscribed to `shard-5` might result in that peer dropping the node. + +## Dependencies + +This document depends on: +* [SSZ spec](https://github.com/ethereum/eth2.0-specs/blob/master/specs/simple-serialize.md) +* [Phase 0 spec](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/core/0_beacon-chain.md) + +## API + +### Sync + +The following is a basic sync protocol akin to eth1.0. _This is very likely to change pending input from those intimately familiar with the pain points of 1.0 sync_. + +`status` message is sent in the initial handshake between two peers. After handshake and status exchange, the peer with higher `latest_finalized_epoch` or, if epochs are equal, the higher `best_slot` sends a list of `beacon_block_roots` via `send_beacon_block_roots`. + +Status handshake fields: +* `protocol_version` +* `network_id` +* `latest_finalized_root` +* `latest_finalized_epoch` +* `best_root` +* `best_slot` + +### Beacon Blocks + +Supported pubsub topics: +* `beacon` + +The following definitions are used in the API: +* `block_header`: a serialized `BeaconBlock` in which `BeaconBlock.body` is the `hash_tree_root` of the associated `BeaconBlockBody`. +* `block_body`: a serialied `BeaconBlockBody`. +* `block_root`: the `hash_tree_root` of a `BeaconBlock`. + +API: +* `send_beacon_block_roots(block_roots)`: Sends list of `block_roots` to peer. +* `send_beacon_block_headers(block_headers)`: Sends list of `block_headers` to peer. +* `request_beacon_block_headers(block_roots)`: Requests the associated `block_headers` for the given `block_roots` from peer. +* `send_beacon_block_bodies(block_bodies)`: Sends list of `block_bodies` to peer. +* `request_beacon_block_bodies(block_roots)`: Requests the associated `block_bodies` for the given `block_roots` from peer. + +Notes: +* It is assumed that both the associated `BeaconBlock` and `BeaconBlockBody` can be looked up via `block_root`. + +### Attestations + +Supported pubsub topics: +* `beacon` +* all `shard-{number}` topics + +The following definitions are used in the API: +* `attestation`: a serialized `Attestation` with full serialized `AttestationData` for `Attestation.data`. + +API: +* `send_attestations(attestations)`: Sends list of `attestations` to peer. + +Notes: +* It is expected that an attestation is only broadcast to either `beacon` topic or `shard-{attestation.data.shard}` topic. Broadcasting to mismatched shard topics is considered bad form. +* It is expected that only aggregate attestations are broadcast to the `beacon` topic. Repeated broadcasting of attestations with a signle signer to the `beacon` topic is considered bad form. +* There is a shard subnet design decision here. Due to the likelihood of `attestation.data` to be highly repeated across a committee during a given slot, it could be valuable to just pass the `attestation` with a `root` in the `attestation.data` field. If the recipient does not already have an `AttestationData` for the received `root`, then the recipient would explicitly request the root. This reduces the total data passed by 184 bytes in the case that the recipient has already received the `attestation.data` but increases the rounds of communication when they haven't. +* We do not currently specify a getter method for an attestation by its `root`. Due to the diverse ways attestations might both be aggregated and stored, it is not feasible to reliably lookup via a `root`. The attestations that a client cares about are (1) those that made it on-chain into a `BeaconBlock` and (2) the most recent set of attestations being actively broadcast on the wire. We might provide a `request_attestations(slot)` or `request_attestations(epoch)` but do not provide it in this minimal API specification. + +### Exits + +Supported pubsub topics: +* `beacon` + +The following definitions are used in the API: +* `exit`: a serialized `Exit`. + +API: +* `send_exit(exit)`: Sends `exit` to peer. + +Notes: +* We do not specify a getter for an exit by its `root`. Standard usage is for \ No newline at end of file