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

Add support for transfers between withdrawn accounts #601

Merged
merged 10 commits into from Feb 12, 2019
47 changes: 47 additions & 0 deletions specs/core/0_beacon-chain.md
Expand Up @@ -38,6 +38,8 @@
- [`DepositInput`](#depositinput)
- [Exits](#exits)
- [`Exit`](#exit)
- [Transfers](#transfers)
- [`Transfer`](#transfer)
- [Beacon chain blocks](#beacon-chain-blocks)
- [`BeaconBlock`](#beaconblock)
- [`BeaconBlockBody`](#beaconblockbody)
Expand Down Expand Up @@ -231,6 +233,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code. Be
| `ENTRY_EXIT_DELAY` | `2**2` (= 4) | epochs | 25.6 minutes |
| `ETH1_DATA_VOTING_PERIOD` | `2**4` (= 16) | epochs | ~1.7 hours |
| `MIN_VALIDATOR_WITHDRAWAL_EPOCHS` | `2**8` (= 256) | epochs | ~27 hours |
| `MIN_EXIT_EPOCHS_BEFORE_TRANSFER` | `2**13` (= 8,192) | epochs | ~36 days |

### State list lengths

Expand Down Expand Up @@ -269,6 +272,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code. Be
| `MAX_ATTESTATIONS` | `2**7` (= 128) |
| `MAX_DEPOSITS` | `2**4` (= 16) |
| `MAX_EXITS` | `2**4` (= 16) |
| `MAX_TRANSFERS` | `2**4` (= 16) |

### Signature domains

Expand All @@ -279,6 +283,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code. Be
| `DOMAIN_PROPOSAL` | `2` |
| `DOMAIN_EXIT` | `3` |
| `DOMAIN_RANDAO` | `4` |
| `DOMAIN_TRANSFER` | `5` |

## Data structures

Expand Down Expand Up @@ -440,6 +445,27 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git
}
```

##### `Transfer`

```python
{
# Sender index
'from': 'uint64',
# Recipient index
'to': 'uint64',
JustinDrake marked this conversation as resolved.
Show resolved Hide resolved
# Amount in Gwei
'amount': 'uint64',
# Fee in Gwei for block proposer
'fee': 'uint64',
# Inclusion slot
'slot': 'uint64',
# Sender withdrawal pubkey
'pubkey': 'bytes48',
# Sender signature
'signature': 'bytes96',
}
```

### Beacon chain blocks

#### `BeaconBlock`
Expand Down Expand Up @@ -468,6 +494,7 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git
'attestations': [Attestation],
'deposits': [Deposit],
'exits': [Exit],
'transfers': [Transfer],
}
```

Expand Down Expand Up @@ -1766,6 +1793,26 @@ For each `exit` in `block.body.exits`:
* Verify that `bls_verify(pubkey=validator.pubkey, message_hash=exit_message, signature=exit.signature, domain=get_domain(state.fork, exit.epoch, DOMAIN_EXIT))`.
* Run `initiate_validator_exit(state, exit.validator_index)`.

##### Transfers

Note: Transfers are a temporary functionality for phases 0 and 1, to be removed in phase 2.

Verify that `len(block.body.transfers) <= MAX_TRANSFERS` and that all transfers are distinct.

For each `transfer` in `block.body.transfers`:

* Verify that `state.validator_balances[transfer.from] >= transfer.amount`.
* Verify that `state.validator_balances[transfer.from] >= transfer.fee`.
* Verify that `state.validator_balances[transfer.from] == transfer.amount + transfer.fee` or `state.validator_balances[transfer.from] >= transfer.amount + transfer.fee + MIN_DEPOSIT_AMOUNT`.
* Verify that `transfer.slot == state.slot`.
* Verify that `get_current_epoch(state) >= state.validator_registry[transfer.from].exit_epoch + MIN_EXIT_EPOCHS_BEFORE_TRANSFER`.
* Verify that `state.validator_registry[transfer.from].withdrawal_credentials == BLS_WITHDRAWAL_PREFIX_BYTE + hash(transfer.pubkey)[1:]`.
* Let `transfer_message = hash_tree_root(Transfer(from=transfer.from, to=transfer.to, amount=transfer.amount, fee=transfer.fee, slot=transfer.slot, signature=EMPTY_SIGNATURE))`.
* Verify that `bls_verify(pubkey=transfer.pubkey, message_hash=transfer_message, signature=transfer.signature, domain=get_domain(state.fork, slot_to_epoch(transfer.slot), DOMAIN_TRANSFER))`.
* Set `state.validator_balances[transfer.from] -= transfer.amount + transfer.fee`.
* Set `state.validator_balances[transfer.to] += transfer.amount`.
* Set `state.validator_balances[get_beacon_proposer_index(state, state.slot)] += transfer.fee`.

### Per-epoch processing

The steps below happen when `(state.slot + 1) % EPOCH_LENGTH == 0`.
Expand Down