Only store a 32 byte root for every shard block Rationale: originally, I added shard block chunking (store 4 chunks for every shard block instead of one root) to facilitate construction of data availability roots. However, it turns out that there is an easier technique. Set the width of the data availability rectangle's rows to be 1/4 the max size of a shard block, so each block would fill multiple rows. Then, non-full blocks will generally create lots of zero rows. For example if the block bodies are `31415926535` and `897932` with a max size of 24 bytes, the rows might look like this: ``` 31415926 53500000 00000000 89793200 00000000 00000000 ``` Zero rows would extend rightward to complete zero rows, and when extending downward we can count the number of zero rows, and reduce the number of extra rows that we make, so we only make a new row for every nonzero row in the original data. This way we get only a close-to-optimal ~4-5x blowup in the data even if the data has zero rows in the middle.
4.0 KiB
Table of Contents generated with DocToc
Ethereum 2.0 Phase 1 -- Shard Transition and Fraud Proofs
Notice: This document is a work-in-progress for researchers and implementers.
Table of contents
TODO
Introduction
This document describes the shard transition function and fraud proofs as part of Phase 1 of Ethereum 2.0.
Fraud proofs
TODO. The intent is to have a single universal fraud proof type, which contains the following parts:
- An on-time attestation on some
shard
signing aShardTransition
- An index
i
of a particular position to focus on - The
ShardTransition
itself - The full body of the block
- A Merkle proof to the
shard_states
in the parent block the attestation is referencing
The proof verifies that one of the two conditions is false:
custody_bits[i][j] != generate_custody_bit(subkey, block_contents)
for anyj
execute_state_transition(shard, slot, transition.shard_states[i-1].data, hash_tree_root(parent), get_shard_proposer_index(state, shard, slot), block_contents) != transition.shard_states[i].data
(ifi=0
then instead useparent.shard_states[shard][-1].data
)
Shard state transition function
def shard_state_transition(shard: Shard,
slot: Slot,
pre_state: Root,
previous_beacon_root: Root,
proposer_pubkey: BLSPubkey,
block_data: ByteList[MAX_SHARD_BLOCK_SIZE]) -> Root:
# We will add something more substantive in phase 2
return hash(pre_state + hash_tree_root(previous_beacon_root) + hash_tree_root(block_data))
Honest committee member behavior
Suppose you are a committee member on shard shard
at slot current_slot
. Let state
be the head beacon state you are building on, and let QUARTER_PERIOD = SECONDS_PER_SLOT // 4
. 2 * QUARTER_PERIOD
seconds into slot slot
, run the following procedure:
- Initialize
proposals = []
,shard_states = []
,shard_state = state.shard_states[shard][-1]
,start_slot = shard_state.slot
. - For
slot in get_offset_slots(state, start_slot)
, do the following:- Look for all valid proposals for
slot
; that is, a Bytesproposal
whereshard_state_transition(shard, slot, shard_state, get_block_root_at_slot(state, state.slot - 1), get_shard_proposer_index(state, shard, slot), proposal)
returns a result and does not throw an exception. Letchoices
be the set of non-empty valid proposals you discover. - If
len(choices) == 0
, doproposals.append(make_empty_proposal(shard_state, slot))
- If
len(choices) == 1
, doproposals.append(choices[0])
- If
len(choices) > 1
, letwinning_proposal
be the proposal with the largest number of total attestations from slots instate.shard_next_slots[shard]....slot-1
supporting it or any of its descendants, breaking ties by choosing the first proposal locally seen. Doproposals.append(winning_proposal)
. - If
proposals[-1]
is NOT an empty proposal, setshard_state = shard_state_transition(shard, slot, shard_state, get_block_root_at_slot(state, state.slot - 1), get_shard_proposer_index(state, shard, slot), proposals[-1])
and doshard_states.append(shard_state)
. If it is an empty proposal, leaveshard_state
unchanged.
- Look for all valid proposals for
Make an attestation using shard_data_roots = [hash_tree_root(proposal) for proposal in proposals]
and shard_state_roots = shard_states
.