Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parent root reconstruction + granular state roots + body/header segregation #649

Closed
wants to merge 53 commits into from
Closed
Changes from 11 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
9cfb548
Self sufficient BeaconState
JustinDrake Feb 18, 2019
4c92463
Update 0_beacon-chain.md
JustinDrake Feb 18, 2019
87682c8
Update 0_beacon-chain.md
JustinDrake Feb 18, 2019
f252e0a
Update 0_beacon-chain.md
JustinDrake Feb 19, 2019
f6b4155
Update 0_beacon-chain.md
JustinDrake Feb 19, 2019
c55fa14
Update 0_beacon-chain.md
JustinDrake Feb 19, 2019
670c605
Update 0_beacon-chain.md
JustinDrake Feb 19, 2019
2069c43
Update 0_beacon-chain.md
JustinDrake Feb 19, 2019
230ba9c
Update 0_beacon-chain.md
JustinDrake Feb 19, 2019
51aa7c3
Update 0_beacon-chain.md
JustinDrake Feb 19, 2019
85e77ff
Update 0_beacon-chain.md
JustinDrake Feb 19, 2019
e5f186d
Update 0_beacon-chain.md
JustinDrake Feb 19, 2019
cf92cc5
Update 0_beacon-chain.md
JustinDrake Feb 19, 2019
6740fe8
Update 0_beacon-chain.md
JustinDrake Feb 19, 2019
05b680a
Update 0_beacon-chain.md
JustinDrake Feb 19, 2019
cc43eb0
Update 0_beacon-chain.md
JustinDrake Feb 19, 2019
62fd49f
Update 0_beacon-chain.md
JustinDrake Feb 19, 2019
e93337a
Apply suggestions from code review
djrtwo Feb 20, 2019
0c23e47
Update 0_beacon-chain.md
JustinDrake Feb 20, 2019
0a0958a
Update 0_beacon-chain.md
JustinDrake Feb 21, 2019
93e4f7f
Update 0_beacon-chain.md
JustinDrake Feb 21, 2019
0dd0571
Update 0_beacon-chain.md
JustinDrake Feb 21, 2019
dc11528
Merge branch 'dev' into JustinDrake-patch-1
JustinDrake Feb 22, 2019
b40f080
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
f2521c1
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
cdab81f
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
f7039f7
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
e862bbc
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
3f36be3
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
9c52adf
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
8419fd6
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
bdb1aff
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
8a179a6
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
c940ae5
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
1c9a69a
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
47dc3c9
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
d1b9d01
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
a809048
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
160e5d3
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
95553e7
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
4205e11
Update 0_beacon-chain.md
JustinDrake Feb 22, 2019
dce225b
Update 0_beacon-chain.md
JustinDrake Feb 23, 2019
bf7dabc
Update 0_beacon-chain.md
JustinDrake Feb 23, 2019
1353120
Update 0_beacon-chain.md
JustinDrake Feb 23, 2019
584df86
Merge branch 'dev' into JustinDrake-patch-1
JustinDrake Feb 25, 2019
aaf1df3
Update 0_beacon-chain.md
JustinDrake Feb 25, 2019
eff3d6b
Apply suggestions from code review
hwwhww Feb 25, 2019
a30cf33
Merge branch 'dev' into JustinDrake-patch-1
djrtwo Feb 28, 2019
d7fe006
Apply suggestions from code review
djrtwo Feb 28, 2019
8d9f47d
move historical batching to per epoch
djrtwo Feb 28, 2019
cd18ad1
Update specs/core/0_beacon-chain.md
djrtwo Mar 1, 2019
e665741
Update 0_beacon-chain.md
JustinDrake Mar 2, 2019
7e3e9ae
Merge branch 'dev' into JustinDrake-patch-1
djrtwo Mar 2, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 57 additions & 43 deletions specs/core/0_beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
- [Block roots](#block-roots)
- [Per-block processing](#per-block-processing)
- [Slot](#slot-1)
- [Block roots](#block-roots-1)
- [Block signature](#block-signature)
- [RANDAO](#randao)
- [Eth1 data](#eth1-data)
Expand Down Expand Up @@ -184,7 +185,6 @@ Code snippets appearing in `this style` are to be interpreted as Python code.
| `SHARD_COUNT` | `2**10` (= 1,024) |
| `TARGET_COMMITTEE_SIZE` | `2**7` (= 128) |
| `MAX_BALANCE_CHURN_QUOTIENT` | `2**5` (= 32) |
| `BEACON_CHAIN_SHARD_NUMBER` | `2**64 - 1` |
| `MAX_INDICES_PER_SLASHABLE_VOTE` | `2**12` (= 4,096) |
| `MAX_EXIT_DEQUEUES_PER_EPOCH` | `2**2` (= 4) |
| `SHUFFLE_ROUND_COUNT` | 90 |
Expand Down Expand Up @@ -469,24 +469,17 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git

```python
{
# Header
'slot': 'uint64',
'parent_root': 'bytes32',
'state_root': 'bytes32',
'randao_reveal': 'bytes96',
'eth1_data': Eth1Data,

# Body
'header': Proposal,
'body': BeaconBlockBody,
# Signature
'signature': 'bytes96',
}
```

#### `BeaconBlockBody`

```python
{
'randao_reveal': 'bytes96',
djrtwo marked this conversation as resolved.
Show resolved Hide resolved
'eth1_data': Eth1Data,
'proposer_slashings': [ProposerSlashing],
'attester_slashings': [AttesterSlashing],
'attestations': [Attestation],
Expand All @@ -502,10 +495,12 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git
{
JustinDrake marked this conversation as resolved.
Show resolved Hide resolved
# Slot number
'slot': 'uint64',
# Shard number (`BEACON_CHAIN_SHARD_NUMBER` for beacon chain)
'shard': 'uint64',
JustinDrake marked this conversation as resolved.
Show resolved Hide resolved
# Parent root
'parent_root': 'bytes32',
# Block root
'block_root': 'bytes32',
# State root
'state_root': 'bytes32',
# Signature
'signature': 'bytes96',
}
Expand Down Expand Up @@ -1412,34 +1407,48 @@ For convenience, we provide the interface to the contract here:

## On genesis

A valid block with slot `GENESIS_SLOT` (a "genesis block") has the following values. Other validity rules (e.g. requiring a signature) do not apply.
When enough full deposits have been made to the deposit contract a `Eth2Genesis` log is emitted. The genesis block and state are defined by `get_genesis_beacon_block` and `get_genesis_beacon_state` where:

* `genesis_validator_deposits` is the list of deposits, ordered chronologically, up to and including the deposit that triggered the `Eth2Genesis` log
* `genesis_time` is timestamp specified in the `Eth2Genesis` log
* `latest_eth1_data` is the `Eth1Data` when `Eth2Genesis` is emitted

```python
{
slot=GENESIS_SLOT,
parent_root=ZERO_HASH,
state_root=GENESIS_STATE_ROOT,
randao_reveal=EMPTY_SIGNATURE,
eth1_data=Eth1Data(
deposit_root=ZERO_HASH,
block_hash=ZERO_HASH
),
signature=EMPTY_SIGNATURE,
body=BeaconBlockBody(
def get_genesis_beacon_block(state: BeaconState) -> BeaconBlock
JustinDrake marked this conversation as resolved.
Show resolved Hide resolved
"""
Get the genesis ``BeaconBlock``.
"""
body = BeaconBlockBody(
randao_reveal=EMPTY_SIGNATURE,
eth1_data=Eth1Data(
deposit_root=ZERO_HASH,
block_hash=ZERO_HASH
),
proposer_slashings=[],
attester_slashings=[],
attestations=[],
deposits=[],
exits=[],
),
transfers=[],
)

return BeaconBlock(
header=Proposal(
slot=GENESIS_SLOT,
parent_root=ZERO_HASH,
block_root=tree_hash_root(body),
JustinDrake marked this conversation as resolved.
Show resolved Hide resolved
state_root=hash_tree_root(state),
signature=EMPTY_SIGNATURE,
),
body=body
)
}
```

`GENESIS_STATE_ROOT` (in the above "genesis block") is generated from the `get_genesis_beacon_state` function below. When enough full deposits have been made to the deposit contract and the `Eth2Genesis` log has been emitted, `get_genesis_beacon_state` will execute to compute the `hash_tree_root` of `BeaconState`.

```python
def get_genesis_beacon_state(genesis_validator_deposits: List[Deposit],
genesis_time: int,
genesis_block_root: Bytes32,
latest_eth1_data: Eth1Data) -> BeaconState:
"""
Get the genesis ``BeaconState``.
Expand Down Expand Up @@ -1488,6 +1497,8 @@ def get_genesis_beacon_state(genesis_validator_deposits: List[Deposit],
deposit_index=len(genesis_validator_deposits)
)

state.latest_block_roots[GENESIS_SLOT % LATEST_BLOCK_ROOTS_LENGTH] = genesis_block_root

# Process genesis deposits
for deposit in genesis_validator_deposits:
process_deposit(state, deposit)
Expand Down Expand Up @@ -1519,7 +1530,7 @@ For a beacon chain block, `block`, to be processed by a node, the following cond

* The parent block with root `block.parent_root` has been processed and accepted.
* An Ethereum 1.0 block pointed to by the `state.latest_eth1_data.block_hash` has been processed and accepted.
* The node's Unix time is greater than or equal to `state.genesis_time + (block.slot - GENESIS_SLOT) * SECONDS_PER_SLOT`. (Note that leap seconds mean that slots will occasionally last `SECONDS_PER_SLOT + 1` or `SECONDS_PER_SLOT - 1` seconds, possibly several times a year.)
* The node's Unix time is greater than or equal to `state.genesis_time + (block.header.slot - GENESIS_SLOT) * SECONDS_PER_SLOT`. (Note that leap seconds mean that slots will occasionally last `SECONDS_PER_SLOT + 1` or `SECONDS_PER_SLOT - 1` seconds, possibly several times a year.)

If these conditions are not met, the client should delay processing the beacon block until the conditions are all satisfied.

Expand All @@ -1539,9 +1550,9 @@ def get_ancestor(store: Store, block: BeaconBlock, slot: Slot) -> BeaconBlock:
"""
Get the ancestor of ``block`` with slot number ``slot``; return ``None`` if not found.
"""
if block.slot == slot:
if block.header.slot == slot:
return block
elif block.slot < slot:
elif block.header.slot < slot:
return None
else:
return get_ancestor(store, store.get_parent(block), slot)
Expand Down Expand Up @@ -1569,7 +1580,7 @@ def lmd_ghost(store: Store, start_state: BeaconState, start_block: BeaconBlock)
return sum(
get_effective_balance(start_state.validator_balances[validator_index]) // FORK_CHOICE_BALANCE_INCREMENT
for validator_index, target in attestation_targets
if get_ancestor(store, target, block.slot) == block
if get_ancestor(store, target, block.header.slot) == block
)

head = start_block
Expand Down Expand Up @@ -1604,8 +1615,7 @@ Below are the processing steps that happen at every slot.

#### Block roots

* Let `previous_block_root` be the `hash_tree_root` of the previous beacon block processed in the chain.
* Set `state.latest_block_roots[(state.slot - 1) % LATEST_BLOCK_ROOTS_LENGTH] = previous_block_root`.
* Set `state.latest_block_roots[state.slot % LATEST_BLOCK_ROOTS_LENGTH] = get_block_root(state, state.slot - 1)`.
* If `state.slot % LATEST_BLOCK_ROOTS_LENGTH == 0` append `merkle_root(state.latest_block_roots)` to `state.batched_block_roots`.

### Per-block processing
Expand All @@ -1614,23 +1624,28 @@ Below are the processing steps that happen at every `block`.

#### Slot

* Verify that `block.slot == state.slot`.
* Verify that `block.header.slot == state.slot`.

#### Block roots

* Verify that `block.header.block_root == tree_hash_root(block.body)`.
* Set `state.latest_block_roots[state.slot % LATEST_BLOCK_ROOTS_LENGTH] = block.header.block_root`.
JustinDrake marked this conversation as resolved.
Show resolved Hide resolved
* Verify that `block.header.parent_root == get_block_root(state, state.slot - 1)`.

#### Block signature

* Let `proposer = state.validator_registry[get_beacon_proposer_index(state, state.slot)]`.
* Let `proposal = Proposal(block.slot, BEACON_CHAIN_SHARD_NUMBER, signed_root(block, "signature"), block.signature)`.
* Verify that `bls_verify(pubkey=proposer.pubkey, message_hash=signed_root(proposal, "signature"), signature=proposal.signature, domain=get_domain(state.fork, get_current_epoch(state), DOMAIN_PROPOSAL))`.
* Verify that `bls_verify(pubkey=proposer.pubkey, message_hash=signed_root(block.header, "signature"), signature=block.header.signature, domain=get_domain(state.fork, get_current_epoch(state), DOMAIN_PROPOSAL))`.

#### RANDAO

* Verify that `bls_verify(pubkey=proposer.pubkey, message_hash=hash_tree_root(get_current_epoch(state)), signature=block.randao_reveal, domain=get_domain(state.fork, get_current_epoch(state), DOMAIN_RANDAO))`.
* Set `state.latest_randao_mixes[get_current_epoch(state) % LATEST_RANDAO_MIXES_LENGTH] = xor(get_randao_mix(state, get_current_epoch(state)), hash(block.randao_reveal))`.
* Verify that `bls_verify(pubkey=proposer.pubkey, message_hash=hash_tree_root(get_current_epoch(state)), signature=block.body.randao_reveal, domain=get_domain(state.fork, get_current_epoch(state), DOMAIN_RANDAO))`.
* Set `state.latest_randao_mixes[get_current_epoch(state) % LATEST_RANDAO_MIXES_LENGTH] = xor(get_randao_mix(state, get_current_epoch(state)), hash(block.body.randao_reveal))`.

#### Eth1 data

* If there exists an `eth1_data_vote` in `state.eth1_data_votes` for which `eth1_data_vote.eth1_data == block.eth1_data` (there will be at most one), set `eth1_data_vote.vote_count += 1`.
* Otherwise, append to `state.eth1_data_votes` a new `Eth1DataVote(eth1_data=block.eth1_data, vote_count=1)`.
* If there exists an `eth1_data_vote` in `state.eth1_data_votes` for which `eth1_data_vote.eth1_data == block.body.eth1_data` (there will be at most one), set `eth1_data_vote.vote_count += 1`.
* Otherwise, append to `state.eth1_data_votes` a new `Eth1DataVote(eth1_data=block.body.eth1_data, vote_count=1)`.

#### Transactions

Expand All @@ -1642,7 +1657,6 @@ For each `proposer_slashing` in `block.body.proposer_slashings`:

* Let `proposer = state.validator_registry[proposer_slashing.proposer_index]`.
* Verify that `proposer_slashing.proposal_1.slot == proposer_slashing.proposal_2.slot`.
* Verify that `proposer_slashing.proposal_1.shard == proposer_slashing.proposal_2.shard`.
* Verify that `proposer_slashing.proposal_1.block_root != proposer_slashing.proposal_2.block_root`.
* Verify that `proposer.slashed_epoch > get_current_epoch(state)`.
* Verify that `bls_verify(pubkey=proposer.pubkey, message_hash=signed_root(proposer_slashing.proposal_1, "signature"), signature=proposer_slashing.proposal_1.signature, domain=get_domain(state.fork, slot_to_epoch(proposer_slashing.proposal_1.slot), DOMAIN_PROPOSAL))`.
Expand Down Expand Up @@ -2060,7 +2074,7 @@ def process_exit_queue(state: BeaconState) -> None:

### State root verification

Verify `block.state_root == hash_tree_root(state)` if there exists a `block` for the slot being processed.
Verify `block.header.state_root == hash_tree_root(state)` if there exists a `block` for the slot being processed.

# References

Expand Down