Skip to content

Commit

Permalink
Remove shard block chunking
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
vbuterin authored Jan 8, 2020
1 parent 9dd8d1d commit 71fdce0
Showing 1 changed file with 8 additions and 25 deletions.
33 changes: 8 additions & 25 deletions specs/core/1_beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
- [`get_previous_slot`](#get_previous_slot)
- [`pack_compact_validator`](#pack_compact_validator)
- [`committee_to_compact_committee`](#committee_to_compact_committee)
- [`chunks_to_body_root`](#chunks_to_body_root)
- [Beacon state accessors](#beacon-state-accessors)
- [`get_active_shard_count`](#get_active_shard_count)
- [`get_online_validator_indices`](#get_online_validator_indices)
Expand Down Expand Up @@ -104,12 +103,10 @@ Configuration is not namespaced. Instead it is strictly an extension;
| `LIGHT_CLIENT_COMMITTEE_SIZE` | `2**7` (= 128) |
| `LIGHT_CLIENT_COMMITTEE_PERIOD` | `Epoch(2**8)` (= 256) | epochs | ~27 hours |
| `SHARD_COMMITTEE_PERIOD` | `Epoch(2**8)` (= 256) | epochs | ~27 hours |
| `SHARD_BLOCK_CHUNK_SIZE` | `2**18` (= 262,144) | |
| `MAX_SHARD_BLOCK_CHUNKS` | `2**2` (= 4) | |
| `TARGET_SHARD_BLOCK_SIZE` | `3 * 2**16` (= 196,608) | |
| `MAX_SHARD_BLOCK_SIZE` | `2**20 (= 1,048,576)` | |
| `TARGET_SHARD_BLOCK_SIZE` | `2**18 (= 262,144)` | |
| `SHARD_BLOCK_OFFSETS` | `[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233]` | |
| `MAX_SHARD_BLOCKS_PER_ATTESTATION` | `len(SHARD_BLOCK_OFFSETS)` | |
| `EMPTY_CHUNK_ROOT` | `hash_tree_root(ByteList[SHARD_BLOCK_CHUNK_SIZE]())` | |
| `MAX_GASPRICE` | `Gwei(2**14)` (= 16,384) | Gwei | |
| `MIN_GASPRICE` | `Gwei(2**5)` (= 32) | Gwei | |
| `GASPRICE_ADJUSTMENT_COEFFICIENT` | `2**3` (= 8) | |
Expand Down Expand Up @@ -305,7 +302,7 @@ class ShardBlockWrapper(Container):
shard_parent_root: Root
beacon_parent_root: Root
slot: Slot
body: ByteList[MAX_SHARD_BLOCK_CHUNKS * SHARD_BLOCK_CHUNK_SIZE]
body: ByteList[MAX_SHARD_BLOCK_SIZE]
signature: BLSSignature
```

Expand Down Expand Up @@ -338,7 +335,7 @@ class ShardTransition(Container):
# Shard block lengths
shard_block_lengths: List[uint64, MAX_SHARD_BLOCKS_PER_ATTESTATION]
# Shard data roots
shard_data_roots: List[List[Bytes32, MAX_SHARD_BLOCK_CHUNKS], MAX_SHARD_BLOCKS_PER_ATTESTATION]
shard_data_roots: List[Bytes32, MAX_SHARD_BLOCKS_PER_ATTESTATION]
# Intermediate shard states
shard_states: List[ShardState, MAX_SHARD_BLOCKS_PER_ATTESTATION]
# Proposer signature aggregate
Expand Down Expand Up @@ -411,15 +408,6 @@ def committee_to_compact_committee(state: BeaconState, committee: Sequence[Valid
return CompactCommittee(pubkeys=pubkeys, compact_validators=compact_validators)
```

#### `chunks_to_body_root`

```python
def chunks_to_body_root(chunks: List[Bytes32, MAX_SHARD_BLOCK_CHUNKS]) -> Root:
return hash_tree_root(Vector[Bytes32, MAX_SHARD_BLOCK_CHUNKS](
chunks + [EMPTY_CHUNK_ROOT] * (MAX_SHARD_BLOCK_CHUNKS - len(chunks))
))
```

### Beacon state accessors

#### `get_active_shard_count`
Expand Down Expand Up @@ -670,20 +658,18 @@ def apply_shard_transition(state: BeaconState, shard: Shard, transition: ShardTr
shard_parent_root=shard_parent_root,
parent_hash=get_block_root_at_slot(state, get_previous_slot(state.slot)),
slot=offset_slots[i],
body_root=chunks_to_body_root(transition.shard_data_roots[i])
body_root=transition.shard_data_roots[i]
))
proposers.append(get_shard_proposer_index(state, shard, offset_slots[i]))
shard_parent_root = hash_tree_root(headers[-1])

# Verify correct calculation of gas prices and slots and chunk roots
# Verify correct calculation of gas prices and slots
prev_gasprice = state.shard_states[shard].gasprice
for i in range(len(offset_slots)):
shard_state = transition.shard_states[i]
block_length = transition.shard_block_lengths[i]
chunks = transition.shard_data_roots[i]
assert shard_state.gasprice == get_updated_gasprice(prev_gasprice, block_length)
assert shard_state.slot == offset_slots[i]
assert len(chunks) == block_length // SHARD_BLOCK_CHUNK_SIZE
prev_gasprice = shard_state.gasprice

# Verify combined proposer signature
Expand All @@ -705,7 +691,7 @@ def apply_shard_transition(state: BeaconState, shard: Shard, transition: ShardTr
def process_crosslink_for_shard(state: BeaconState,
shard: Shard,
shard_transition: ShardTransition,
attestations: Sequence[Attestation]) -> Root:
attestations: Sequence[Attestation]) -> Root:US
committee = get_beacon_committee(state, get_current_epoch(state), shard)
online_indices = get_online_validator_indices(state)

Expand All @@ -728,10 +714,7 @@ def process_crosslink_for_shard(state: BeaconState,

# Attestation <-> shard transition consistency
assert shard_transition_root == hash_tree_root(shard_transition)
assert (
attestation.data.head_shard_root
== chunks_to_body_root(shard_transition.shard_data_roots[-1])
)
assert attestation.data.head_shard_root == shard_transition.shard_data_roots[-1]

# Apply transition
apply_shard_transition(state, shard, shard_transition)
Expand Down

0 comments on commit 71fdce0

Please sign in to comment.