Skip to content

Commit

Permalink
Merge pull request #2834 from protolambda/withdrawals
Browse files Browse the repository at this point in the history
capella: impl withdrawal tree like deposit tree
  • Loading branch information
djrtwo authored Feb 22, 2022
2 parents cbf314c + 17a7065 commit f912f9d
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 5 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ GENERATOR_VENVS = $(patsubst $(GENERATOR_DIR)/%, $(GENERATOR_DIR)/%venv, $(GENER

MARKDOWN_FILES = $(wildcard $(SPEC_DIR)/phase0/*.md) $(wildcard $(SPEC_DIR)/altair/*.md) $(wildcard $(SSZ_DIR)/*.md) \
$(wildcard $(SPEC_DIR)/bellatrix/*.md) \
$(wildcard $(SPEC_DIR)/capella/*.md) \
$(wildcard $(SPEC_DIR)/custody/*.md) \
$(wildcard $(SPEC_DIR)/das/*.md) \
$(wildcard $(SPEC_DIR)/sharding/*.md)
Expand Down
73 changes: 68 additions & 5 deletions specs/capella/beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,29 @@
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

- [Introduction](#introduction)
- [Custom types](#custom-types)
- [Constants](#constants)
- [Preset](#preset)
- [State list lengths](#state-list-lengths)
- [Configuration](#configuration)
- [Containers](#containers)
- [Extended Containers](#extended-containers)
- [`Validator`](#validator)
- [`BeaconState`](#beaconstate)
- [New containers](#new-containers)
- [`WithdrawalReceipt`](#withdrawalreceipt)
- [Helper functions](#helper-functions)
- [Misc](#misc)
- [`compute_withdrawal_tree_root`](#compute_withdrawal_tree_root)
- [Beacon state mutators](#beacon-state-mutators)
- [`withdraw`](#withdraw)
- [Predicates](#predicates)
- [`is_withdrawable_validator`](#is_withdrawable_validator)
- [Beacon chain state transition function](#beacon-chain-state-transition-function)
- [Epoch processing](#epoch-processing)
- [Withdrawals](#withdrawals)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- /TOC -->

Expand All @@ -32,7 +55,7 @@ to validator withdrawals. Including:

| Name | Value | Unit | Duration |
| - | - | :-: | :-: |
| `WITHDRAWAL_RECEIPT_LIMIT` | `uint64(2**40)` (= 1,099,511,627,776) | withdrawal receipts|
| `WITHDRAWAL_RECEIPTS_TREE_DEPTH` | `uint64(40)` (= 1,099,511,627,776) | capacity for `2**40` withdrawal receipts |

## Configuration

Expand Down Expand Up @@ -97,8 +120,10 @@ class BeaconState(Container):
next_sync_committee: SyncCommittee
# Execution
latest_execution_payload_header: ExecutionPayloadHeader
# Withdrawals
withdrawal_receipts: List[WithdrawalReceipt, WITHDRAWAL_RECEIPT_LIMIT] # [New in Capella]
# Withdrawals [New in Capella]
withdrawal_receipts_merkle_stack: Vector[Root, WITHDRAWAL_RECEIPTS_TREE_DEPTH]
withdrawal_count: uint64
latest_withdrawal_tree_root: Root
```

### New containers
Expand All @@ -112,7 +137,32 @@ class WithdrawalReceipt(Container):
amount: Gwei
```

## Helpers
## Helper functions

### Misc

#### `compute_withdrawal_tree_root`

```python
def compute_withdrawal_tree_root(state: BeaconState) -> Root:
"""
Computes the withdrawal-tree hash-tree-root,
emulating a List[WithdrawalReceipt, 2**WITHDRAWAL_RECEIPTS_TREE_DEPTH].
"""
zero_hashes = [Root()]
for i in range(WITHDRAWAL_RECEIPTS_TREE_DEPTH-1):
zero_hashes.append(hash(zero_hashes[i] + zero_hashes[i]))

size = state.withdrawal_count
node = Root()
for height in range(WITHDRAWAL_RECEIPTS_TREE_DEPTH):
if size % 2 == 1:
node = hash(state.withdrawal_receipts_merkle_stack[i] + node)
else:
node = hash(node + zero_hashes[i])
size /= 2
return hash(node + uint256(state.withdrawal_count).encode_bytes()) # length mix-in
```

### Beacon state mutators

Expand All @@ -128,7 +178,19 @@ def withdraw(state: BeaconState, index: ValidatorIndex, amount: Gwei) -> None:
address=state.validators[index].withdrawal_credentials[12:],
amount=amount,
)
state.withdrawal_receipts.append(receipt)
# Optional: store receipt for later execution as user

# Update state for computation of the withdrawal root
node = hash_tree_root(receipt)
size = uint64(index) + 1
for i in range(WITHDRAWAL_RECEIPTS_TREE_DEPTH):
if size % 2 == 1: # odd size -> even position -> buffer left hand
state.withdrawal_receipts_merkle_stack[i] = node
break

# combine previous left-hand with right hand
node = hash(state.withdrawal_receipts_merkle_stack[i] + node)
size /= 2
```

### Predicates
Expand Down Expand Up @@ -177,4 +239,5 @@ def process_withdrawals(state: BeaconState) -> None:
# TODO, consider the zero-balance case
withdraw(state, ValidatorIndex(index), state.balances[index])
validator.withdrawn_epoch = current_epoch
state.latest_withdrawal_tree_root = compute_withdrawal_tree_root(state)
```

0 comments on commit f912f9d

Please sign in to comment.