Merge branch 'dev' into prev-cur-crosslinks
This commit is contained in:
commit
39b4ef3892
|
@ -10,6 +10,7 @@ This repo hosts the current eth2.0 specifications. Discussions about design rati
|
||||||
|
|
||||||
Core specifications for eth2.0 client validation can be found in [specs/core](specs/core). These are divided into phases. Each subsequent phase depends upon the prior. The current phases specified are:
|
Core specifications for eth2.0 client validation can be found in [specs/core](specs/core). These are divided into phases. Each subsequent phase depends upon the prior. The current phases specified are:
|
||||||
* [Phase 0 -- The Beacon Chain](specs/core/0_beacon-chain.md)
|
* [Phase 0 -- The Beacon Chain](specs/core/0_beacon-chain.md)
|
||||||
|
* [Phase 1 -- Custody game](specs/core/1_custody-game.md)
|
||||||
* [Phase 1 -- Shard Data Chains](specs/core/1_shard-data-chains.md)
|
* [Phase 1 -- Shard Data Chains](specs/core/1_shard-data-chains.md)
|
||||||
|
|
||||||
Accompanying documents can be found in [specs](specs) and include
|
Accompanying documents can be found in [specs](specs) and include
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
- [Time parameters](#time-parameters)
|
- [Time parameters](#time-parameters)
|
||||||
- [State list lengths](#state-list-lengths)
|
- [State list lengths](#state-list-lengths)
|
||||||
- [Reward and penalty quotients](#reward-and-penalty-quotients)
|
- [Reward and penalty quotients](#reward-and-penalty-quotients)
|
||||||
- [Max transactions per block](#max-transactions-per-block)
|
- [Max operations per block](#max-operations-per-block)
|
||||||
- [Signature domains](#signature-domains)
|
- [Signature domains](#signature-domains)
|
||||||
- [Data structures](#data-structures)
|
- [Data structures](#data-structures)
|
||||||
- [Misc dependencies](#misc-dependencies)
|
- [Misc dependencies](#misc-dependencies)
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
- [`Validator`](#validator)
|
- [`Validator`](#validator)
|
||||||
- [`PendingAttestation`](#pendingattestation)
|
- [`PendingAttestation`](#pendingattestation)
|
||||||
- [`HistoricalBatch`](#historicalbatch)
|
- [`HistoricalBatch`](#historicalbatch)
|
||||||
- [Beacon transactions](#beacon-transactions)
|
- [Beacon operations](#beacon-operations)
|
||||||
- [`ProposerSlashing`](#proposerslashing)
|
- [`ProposerSlashing`](#proposerslashing)
|
||||||
- [`AttesterSlashing`](#attesterslashing)
|
- [`AttesterSlashing`](#attesterslashing)
|
||||||
- [`Attestation`](#attestation)
|
- [`Attestation`](#attestation)
|
||||||
|
@ -132,7 +132,7 @@
|
||||||
- [Block header](#block-header)
|
- [Block header](#block-header)
|
||||||
- [RANDAO](#randao)
|
- [RANDAO](#randao)
|
||||||
- [Eth1 data](#eth1-data-1)
|
- [Eth1 data](#eth1-data-1)
|
||||||
- [Transactions](#transactions)
|
- [Operations](#operations)
|
||||||
- [Proposer slashings](#proposer-slashings)
|
- [Proposer slashings](#proposer-slashings)
|
||||||
- [Attester slashings](#attester-slashings)
|
- [Attester slashings](#attester-slashings)
|
||||||
- [Attestations](#attestations)
|
- [Attestations](#attestations)
|
||||||
|
@ -261,8 +261,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code.
|
||||||
* The `BASE_REWARD_QUOTIENT` parameter dictates the per-epoch reward. It corresponds to ~2.54% annual interest assuming 10 million participating ETH in every epoch.
|
* The `BASE_REWARD_QUOTIENT` parameter dictates the per-epoch reward. It corresponds to ~2.54% annual interest assuming 10 million participating ETH in every epoch.
|
||||||
* The `INACTIVITY_PENALTY_QUOTIENT` equals `INVERSE_SQRT_E_DROP_TIME**2` where `INVERSE_SQRT_E_DROP_TIME := 2**12 epochs` (~18 days) is the time it takes the inactivity penalty to reduce the balance of non-participating [validators](#dfn-validator) to about `1/sqrt(e) ~= 60.6%`. Indeed, the balance retained by offline [validators](#dfn-validator) after `n` epochs is about `(1 - 1/INACTIVITY_PENALTY_QUOTIENT)**(n**2/2)` so after `INVERSE_SQRT_E_DROP_TIME` epochs it is roughly `(1 - 1/INACTIVITY_PENALTY_QUOTIENT)**(INACTIVITY_PENALTY_QUOTIENT/2) ~= 1/sqrt(e)`.
|
* The `INACTIVITY_PENALTY_QUOTIENT` equals `INVERSE_SQRT_E_DROP_TIME**2` where `INVERSE_SQRT_E_DROP_TIME := 2**12 epochs` (~18 days) is the time it takes the inactivity penalty to reduce the balance of non-participating [validators](#dfn-validator) to about `1/sqrt(e) ~= 60.6%`. Indeed, the balance retained by offline [validators](#dfn-validator) after `n` epochs is about `(1 - 1/INACTIVITY_PENALTY_QUOTIENT)**(n**2/2)` so after `INVERSE_SQRT_E_DROP_TIME` epochs it is roughly `(1 - 1/INACTIVITY_PENALTY_QUOTIENT)**(INACTIVITY_PENALTY_QUOTIENT/2) ~= 1/sqrt(e)`.
|
||||||
|
|
||||||
|
### Max operations per block
|
||||||
### Max transactions per block
|
|
||||||
|
|
||||||
| Name | Value |
|
| Name | Value |
|
||||||
| - | - |
|
| - | - |
|
||||||
|
@ -460,7 +459,7 @@ The types are defined topologically to aid in facilitating an executable version
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Beacon transactions
|
### Beacon operations
|
||||||
|
|
||||||
#### `ProposerSlashing`
|
#### `ProposerSlashing`
|
||||||
|
|
||||||
|
@ -1188,6 +1187,9 @@ def verify_indexed_attestation(state: BeaconState, indexed_attestation: IndexedA
|
||||||
custody_bit_0_indices = indexed_attestation.custody_bit_0_indices
|
custody_bit_0_indices = indexed_attestation.custody_bit_0_indices
|
||||||
custody_bit_1_indices = indexed_attestation.custody_bit_1_indices
|
custody_bit_1_indices = indexed_attestation.custody_bit_1_indices
|
||||||
|
|
||||||
|
# ensure no duplicate indices across custody bits
|
||||||
|
assert len(set(custody_bit_0_indices).intersection(set(custody_bit_1_indices))) == 0
|
||||||
|
|
||||||
if len(custody_bit_1_indices) > 0: # [TO BE REMOVED IN PHASE 1]
|
if len(custody_bit_1_indices) > 0: # [TO BE REMOVED IN PHASE 1]
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -2243,7 +2245,7 @@ def process_eth1_data(state: BeaconState, block: BeaconBlock) -> None:
|
||||||
state.eth1_data_votes.append(Eth1DataVote(eth1_data=block.body.eth1_data, vote_count=1))
|
state.eth1_data_votes.append(Eth1DataVote(eth1_data=block.body.eth1_data, vote_count=1))
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Transactions
|
#### Operations
|
||||||
|
|
||||||
##### Proposer slashings
|
##### Proposer slashings
|
||||||
|
|
||||||
|
@ -2255,7 +2257,7 @@ For each `proposer_slashing` in `block.body.proposer_slashings`, run the followi
|
||||||
def process_proposer_slashing(state: BeaconState,
|
def process_proposer_slashing(state: BeaconState,
|
||||||
proposer_slashing: ProposerSlashing) -> None:
|
proposer_slashing: ProposerSlashing) -> None:
|
||||||
"""
|
"""
|
||||||
Process ``ProposerSlashing`` transaction.
|
Process ``ProposerSlashing`` operation.
|
||||||
Note that this function mutates ``state``.
|
Note that this function mutates ``state``.
|
||||||
"""
|
"""
|
||||||
proposer = state.validator_registry[proposer_slashing.proposer_index]
|
proposer = state.validator_registry[proposer_slashing.proposer_index]
|
||||||
|
@ -2286,7 +2288,7 @@ For each `attester_slashing` in `block.body.attester_slashings`, run the followi
|
||||||
def process_attester_slashing(state: BeaconState,
|
def process_attester_slashing(state: BeaconState,
|
||||||
attester_slashing: AttesterSlashing) -> None:
|
attester_slashing: AttesterSlashing) -> None:
|
||||||
"""
|
"""
|
||||||
Process ``AttesterSlashing`` transaction.
|
Process ``AttesterSlashing`` operation.
|
||||||
Note that this function mutates ``state``.
|
Note that this function mutates ``state``.
|
||||||
"""
|
"""
|
||||||
attestation1 = attester_slashing.attestation_1
|
attestation1 = attester_slashing.attestation_1
|
||||||
|
@ -2300,10 +2302,12 @@ def process_attester_slashing(state: BeaconState,
|
||||||
|
|
||||||
assert verify_indexed_attestation(state, attestation1)
|
assert verify_indexed_attestation(state, attestation1)
|
||||||
assert verify_indexed_attestation(state, attestation2)
|
assert verify_indexed_attestation(state, attestation2)
|
||||||
|
attesting_indices_1 = attestation1.custody_bit_0_indices + attestation1.custody_bit_1_indices
|
||||||
|
attesting_indices_2 = attestation2.custody_bit_0_indices + attestation2.custody_bit_1_indices
|
||||||
slashable_indices = [
|
slashable_indices = [
|
||||||
index for index in attestation1.validator_indices
|
index for index in attesting_indices_1
|
||||||
if (
|
if (
|
||||||
index in attestation2.validator_indices and
|
index in attesting_indices_2 and
|
||||||
is_slashable_validator(state.validator_registry[index], get_current_epoch(state))
|
is_slashable_validator(state.validator_registry[index], get_current_epoch(state))
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
@ -2321,7 +2325,7 @@ For each `attestation` in `block.body.attestations`, run the following function:
|
||||||
```python
|
```python
|
||||||
def process_attestation(state: BeaconState, attestation: Attestation) -> None:
|
def process_attestation(state: BeaconState, attestation: Attestation) -> None:
|
||||||
"""
|
"""
|
||||||
Process ``Attestation`` transaction.
|
Process ``Attestation`` operation.
|
||||||
Note that this function mutates ``state``.
|
Note that this function mutates ``state``.
|
||||||
"""
|
"""
|
||||||
assert max(GENESIS_SLOT, state.slot - SLOTS_PER_EPOCH) <= attestation.data.slot
|
assert max(GENESIS_SLOT, state.slot - SLOTS_PER_EPOCH) <= attestation.data.slot
|
||||||
|
@ -2370,7 +2374,7 @@ For each `exit` in `block.body.voluntary_exits`, run the following function:
|
||||||
```python
|
```python
|
||||||
def process_voluntary_exit(state: BeaconState, exit: VoluntaryExit) -> None:
|
def process_voluntary_exit(state: BeaconState, exit: VoluntaryExit) -> None:
|
||||||
"""
|
"""
|
||||||
Process ``VoluntaryExit`` transaction.
|
Process ``VoluntaryExit`` operation.
|
||||||
Note that this function mutates ``state``.
|
Note that this function mutates ``state``.
|
||||||
"""
|
"""
|
||||||
validator = state.validator_registry[exit.validator_index]
|
validator = state.validator_registry[exit.validator_index]
|
||||||
|
@ -2406,7 +2410,7 @@ For each `transfer` in `block.body.transfers`, run the following function:
|
||||||
```python
|
```python
|
||||||
def process_transfer(state: BeaconState, transfer: Transfer) -> None:
|
def process_transfer(state: BeaconState, transfer: Transfer) -> None:
|
||||||
"""
|
"""
|
||||||
Process ``Transfer`` transaction.
|
Process ``Transfer`` operation.
|
||||||
Note that this function mutates ``state``.
|
Note that this function mutates ``state``.
|
||||||
"""
|
"""
|
||||||
# Verify the amount and fee aren't individually too big (for anti-overflow purposes)
|
# Verify the amount and fee aren't individually too big (for anti-overflow purposes)
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
- [Constants](#constants)
|
- [Constants](#constants)
|
||||||
- [Misc](#misc)
|
- [Misc](#misc)
|
||||||
- [Time parameters](#time-parameters)
|
- [Time parameters](#time-parameters)
|
||||||
- [Max transactions per block](#max-transactions-per-block)
|
- [Max operations per block](#max-operations-per-block)
|
||||||
- [Signature domains](#signature-domains)
|
- [Signature domains](#signature-domains)
|
||||||
- [Data structures](#data-structures)
|
- [Data structures](#data-structures)
|
||||||
- [Custody objects](#custody-objects)
|
- [Custody objects](#custody-objects)
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
- [`epoch_to_custody_period`](#epoch_to_custody_period)
|
- [`epoch_to_custody_period`](#epoch_to_custody_period)
|
||||||
- [`verify_custody_key`](#verify_custody_key)
|
- [`verify_custody_key`](#verify_custody_key)
|
||||||
- [Per-block processing](#per-block-processing)
|
- [Per-block processing](#per-block-processing)
|
||||||
- [Transactions](#transactions)
|
- [Operations](#operations)
|
||||||
- [Custody reveals](#custody-reveals)
|
- [Custody reveals](#custody-reveals)
|
||||||
- [Chunk challenges](#chunk-challenges)
|
- [Chunk challenges](#chunk-challenges)
|
||||||
- [Bit challenges](#bit-challenges)
|
- [Bit challenges](#bit-challenges)
|
||||||
|
@ -79,7 +79,7 @@ This document details the beacon chain additions and changes in Phase 1 of Ether
|
||||||
| `EPOCHS_PER_CUSTODY_PERIOD` | `2**11` (= 2,048) | epochs | ~9 days |
|
| `EPOCHS_PER_CUSTODY_PERIOD` | `2**11` (= 2,048) | epochs | ~9 days |
|
||||||
| `CUSTODY_RESPONSE_DEADLINE` | `2**14` (= 16,384) | epochs | ~73 days |
|
| `CUSTODY_RESPONSE_DEADLINE` | `2**14` (= 16,384) | epochs | ~73 days |
|
||||||
|
|
||||||
### Max transactions per block
|
### Max operations per block
|
||||||
|
|
||||||
| Name | Value |
|
| Name | Value |
|
||||||
| - | - |
|
| - | - |
|
||||||
|
@ -259,9 +259,9 @@ def verify_custody_key(state: BeaconState, reveal: CustodyKeyReveal) -> bool:
|
||||||
|
|
||||||
## Per-block processing
|
## Per-block processing
|
||||||
|
|
||||||
### Transactions
|
### Operations
|
||||||
|
|
||||||
Add the following transactions to the per-block processing, in order the given below and after all other transactions in phase 0.
|
Add the following operations to the per-block processing, in order the given below and after all other operations in phase 0.
|
||||||
|
|
||||||
#### Custody reveals
|
#### Custody reveals
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
from copy import deepcopy
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import build.phase0.spec as spec
|
||||||
|
from build.phase0.spec import (
|
||||||
|
get_balance,
|
||||||
|
get_beacon_proposer_index,
|
||||||
|
process_attester_slashing,
|
||||||
|
)
|
||||||
|
from tests.phase0.helpers import (
|
||||||
|
get_valid_attester_slashing,
|
||||||
|
)
|
||||||
|
|
||||||
|
# mark entire file as 'attester_slashing'
|
||||||
|
pytestmark = pytest.mark.attester_slashings
|
||||||
|
|
||||||
|
|
||||||
|
def run_attester_slashing_processing(state, attester_slashing, valid=True):
|
||||||
|
"""
|
||||||
|
Run ``process_attester_slashing`` returning the pre and post state.
|
||||||
|
If ``valid == False``, run expecting ``AssertionError``
|
||||||
|
"""
|
||||||
|
post_state = deepcopy(state)
|
||||||
|
|
||||||
|
if not valid:
|
||||||
|
with pytest.raises(AssertionError):
|
||||||
|
process_attester_slashing(post_state, attester_slashing)
|
||||||
|
return state, None
|
||||||
|
|
||||||
|
process_attester_slashing(post_state, attester_slashing)
|
||||||
|
|
||||||
|
slashed_index = attester_slashing.attestation_1.custody_bit_0_indices[0]
|
||||||
|
slashed_validator = post_state.validator_registry[slashed_index]
|
||||||
|
assert not slashed_validator.initiated_exit
|
||||||
|
assert slashed_validator.slashed
|
||||||
|
assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||||
|
assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
|
||||||
|
# lost whistleblower reward
|
||||||
|
assert (
|
||||||
|
get_balance(post_state, slashed_index) <
|
||||||
|
get_balance(state, slashed_index)
|
||||||
|
)
|
||||||
|
proposer_index = get_beacon_proposer_index(state, state.slot)
|
||||||
|
# gained whistleblower reward
|
||||||
|
assert (
|
||||||
|
get_balance(post_state, proposer_index) >
|
||||||
|
get_balance(state, proposer_index)
|
||||||
|
)
|
||||||
|
|
||||||
|
return state, post_state
|
||||||
|
|
||||||
|
|
||||||
|
def test_success_double(state):
|
||||||
|
attester_slashing = get_valid_attester_slashing(state)
|
||||||
|
|
||||||
|
pre_state, post_state = run_attester_slashing_processing(state, attester_slashing)
|
||||||
|
|
||||||
|
return pre_state, attester_slashing, post_state
|
||||||
|
|
||||||
|
|
||||||
|
def test_success_surround(state):
|
||||||
|
attester_slashing = get_valid_attester_slashing(state)
|
||||||
|
|
||||||
|
# set attestion1 to surround attestation 2
|
||||||
|
attester_slashing.attestation_1.data.source_epoch = attester_slashing.attestation_2.data.source_epoch - 1
|
||||||
|
attester_slashing.attestation_1.data.slot = attester_slashing.attestation_2.data.slot + spec.SLOTS_PER_EPOCH
|
||||||
|
|
||||||
|
pre_state, post_state = run_attester_slashing_processing(state, attester_slashing)
|
||||||
|
|
||||||
|
return pre_state, attester_slashing, post_state
|
||||||
|
|
||||||
|
|
||||||
|
def test_same_data(state):
|
||||||
|
attester_slashing = get_valid_attester_slashing(state)
|
||||||
|
|
||||||
|
attester_slashing.attestation_1.data = attester_slashing.attestation_2.data
|
||||||
|
|
||||||
|
pre_state, post_state = run_attester_slashing_processing(state, attester_slashing, False)
|
||||||
|
|
||||||
|
return pre_state, attester_slashing, post_state
|
||||||
|
|
||||||
|
|
||||||
|
def test_no_double_or_surround(state):
|
||||||
|
attester_slashing = get_valid_attester_slashing(state)
|
||||||
|
|
||||||
|
attester_slashing.attestation_1.data.slot += spec.SLOTS_PER_EPOCH
|
||||||
|
|
||||||
|
pre_state, post_state = run_attester_slashing_processing(state, attester_slashing, False)
|
||||||
|
|
||||||
|
return pre_state, attester_slashing, post_state
|
||||||
|
|
||||||
|
|
||||||
|
def test_participants_already_slashed(state):
|
||||||
|
attester_slashing = get_valid_attester_slashing(state)
|
||||||
|
|
||||||
|
# set all indices to slashed
|
||||||
|
attestation_1 = attester_slashing.attestation_1
|
||||||
|
validator_indices = attestation_1.custody_bit_0_indices + attestation_1.custody_bit_1_indices
|
||||||
|
for index in validator_indices:
|
||||||
|
state.validator_registry[index].slashed = True
|
||||||
|
|
||||||
|
pre_state, post_state = run_attester_slashing_processing(state, attester_slashing, False)
|
||||||
|
|
||||||
|
return pre_state, attester_slashing, post_state
|
||||||
|
|
||||||
|
|
||||||
|
def test_custody_bit_0_and_1(state):
|
||||||
|
attester_slashing = get_valid_attester_slashing(state)
|
||||||
|
|
||||||
|
attester_slashing.attestation_1.custody_bit_1_indices = (
|
||||||
|
attester_slashing.attestation_1.custody_bit_0_indices
|
||||||
|
)
|
||||||
|
pre_state, post_state = run_attester_slashing_processing(state, attester_slashing, False)
|
||||||
|
|
||||||
|
return pre_state, attester_slashing, post_state
|
|
@ -12,6 +12,7 @@ from build.phase0.spec import (
|
||||||
Attestation,
|
Attestation,
|
||||||
AttestationData,
|
AttestationData,
|
||||||
AttestationDataAndCustodyBit,
|
AttestationDataAndCustodyBit,
|
||||||
|
AttesterSlashing,
|
||||||
BeaconBlockHeader,
|
BeaconBlockHeader,
|
||||||
Deposit,
|
Deposit,
|
||||||
DepositData,
|
DepositData,
|
||||||
|
@ -19,6 +20,7 @@ from build.phase0.spec import (
|
||||||
ProposerSlashing,
|
ProposerSlashing,
|
||||||
VoluntaryExit,
|
VoluntaryExit,
|
||||||
# functions
|
# functions
|
||||||
|
convert_to_indexed,
|
||||||
get_active_validator_indices,
|
get_active_validator_indices,
|
||||||
get_attestation_participants,
|
get_attestation_participants,
|
||||||
get_block_root,
|
get_block_root,
|
||||||
|
@ -241,6 +243,17 @@ def get_valid_proposer_slashing(state):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_valid_attester_slashing(state):
|
||||||
|
attestation_1 = get_valid_attestation(state)
|
||||||
|
attestation_2 = deepcopy(attestation_1)
|
||||||
|
attestation_2.data.target_root = b'\x01'*32
|
||||||
|
|
||||||
|
return AttesterSlashing(
|
||||||
|
attestation_1=convert_to_indexed(state, attestation_1),
|
||||||
|
attestation_2=convert_to_indexed(state, attestation_2),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_valid_attestation(state, slot=None):
|
def get_valid_attestation(state, slot=None):
|
||||||
if slot is None:
|
if slot is None:
|
||||||
slot = state.slot
|
slot = state.slot
|
||||||
|
|
|
@ -17,6 +17,7 @@ from build.phase0.spec import (
|
||||||
# functions
|
# functions
|
||||||
get_active_validator_indices,
|
get_active_validator_indices,
|
||||||
get_balance,
|
get_balance,
|
||||||
|
get_beacon_proposer_index,
|
||||||
get_block_root,
|
get_block_root,
|
||||||
get_current_epoch,
|
get_current_epoch,
|
||||||
get_domain,
|
get_domain,
|
||||||
|
@ -41,6 +42,7 @@ from tests.phase0.helpers import (
|
||||||
build_empty_block_for_next_slot,
|
build_empty_block_for_next_slot,
|
||||||
force_registry_change_at_next_epoch,
|
force_registry_change_at_next_epoch,
|
||||||
get_valid_attestation,
|
get_valid_attestation,
|
||||||
|
get_valid_attester_slashing,
|
||||||
get_valid_proposer_slashing,
|
get_valid_proposer_slashing,
|
||||||
privkeys,
|
privkeys,
|
||||||
pubkeys,
|
pubkeys,
|
||||||
|
@ -141,6 +143,39 @@ def test_proposer_slashing(state):
|
||||||
return state, [block], test_state
|
return state, [block], test_state
|
||||||
|
|
||||||
|
|
||||||
|
def test_attester_slashing(state):
|
||||||
|
test_state = deepcopy(state)
|
||||||
|
attester_slashing = get_valid_attester_slashing(state)
|
||||||
|
validator_index = attester_slashing.attestation_1.custody_bit_0_indices[0]
|
||||||
|
|
||||||
|
#
|
||||||
|
# Add to state via block transition
|
||||||
|
#
|
||||||
|
block = build_empty_block_for_next_slot(test_state)
|
||||||
|
block.body.attester_slashings.append(attester_slashing)
|
||||||
|
state_transition(test_state, block)
|
||||||
|
|
||||||
|
assert not state.validator_registry[validator_index].initiated_exit
|
||||||
|
assert not state.validator_registry[validator_index].slashed
|
||||||
|
|
||||||
|
slashed_validator = test_state.validator_registry[validator_index]
|
||||||
|
assert not slashed_validator.initiated_exit
|
||||||
|
assert slashed_validator.slashed
|
||||||
|
assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||||
|
assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
|
||||||
|
# lost whistleblower reward
|
||||||
|
assert get_balance(test_state, validator_index) < get_balance(state, validator_index)
|
||||||
|
|
||||||
|
proposer_index = get_beacon_proposer_index(test_state, test_state.slot)
|
||||||
|
# gained whistleblower reward
|
||||||
|
assert (
|
||||||
|
get_balance(test_state, proposer_index) >
|
||||||
|
get_balance(state, proposer_index)
|
||||||
|
)
|
||||||
|
|
||||||
|
return state, [block], test_state
|
||||||
|
|
||||||
|
|
||||||
def test_deposit_in_block(state):
|
def test_deposit_in_block(state):
|
||||||
pre_state = deepcopy(state)
|
pre_state = deepcopy(state)
|
||||||
test_deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry)
|
test_deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry)
|
||||||
|
|
|
@ -22,31 +22,31 @@ def expected_deposit_count(state: BeaconState) -> int:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def process_transaction_type(state: BeaconState,
|
def process_operation_type(state: BeaconState,
|
||||||
transactions: List[Any],
|
operations: List[Any],
|
||||||
max_transactions: int,
|
max_operations: int,
|
||||||
tx_fn: Callable[[BeaconState, Any], None]) -> None:
|
tx_fn: Callable[[BeaconState, Any], None]) -> None:
|
||||||
assert len(transactions) <= max_transactions
|
assert len(operations) <= max_operations
|
||||||
for transaction in transactions:
|
for operation in operations:
|
||||||
tx_fn(state, transaction)
|
tx_fn(state, operation)
|
||||||
|
|
||||||
|
|
||||||
def process_transactions(state: BeaconState, block: BeaconBlock) -> None:
|
def process_operations(state: BeaconState, block: BeaconBlock) -> None:
|
||||||
process_transaction_type(
|
process_operation_type(
|
||||||
state,
|
state,
|
||||||
block.body.proposer_slashings,
|
block.body.proposer_slashings,
|
||||||
spec.MAX_PROPOSER_SLASHINGS,
|
spec.MAX_PROPOSER_SLASHINGS,
|
||||||
spec.process_proposer_slashing,
|
spec.process_proposer_slashing,
|
||||||
)
|
)
|
||||||
|
|
||||||
process_transaction_type(
|
process_operation_type(
|
||||||
state,
|
state,
|
||||||
block.body.attester_slashings,
|
block.body.attester_slashings,
|
||||||
spec.MAX_ATTESTER_SLASHINGS,
|
spec.MAX_ATTESTER_SLASHINGS,
|
||||||
spec.process_attester_slashing,
|
spec.process_attester_slashing,
|
||||||
)
|
)
|
||||||
|
|
||||||
process_transaction_type(
|
process_operation_type(
|
||||||
state,
|
state,
|
||||||
block.body.attestations,
|
block.body.attestations,
|
||||||
spec.MAX_ATTESTATIONS,
|
spec.MAX_ATTESTATIONS,
|
||||||
|
@ -54,14 +54,14 @@ def process_transactions(state: BeaconState, block: BeaconBlock) -> None:
|
||||||
)
|
)
|
||||||
|
|
||||||
assert len(block.body.deposits) == expected_deposit_count(state)
|
assert len(block.body.deposits) == expected_deposit_count(state)
|
||||||
process_transaction_type(
|
process_operation_type(
|
||||||
state,
|
state,
|
||||||
block.body.deposits,
|
block.body.deposits,
|
||||||
spec.MAX_DEPOSITS,
|
spec.MAX_DEPOSITS,
|
||||||
spec.process_deposit,
|
spec.process_deposit,
|
||||||
)
|
)
|
||||||
|
|
||||||
process_transaction_type(
|
process_operation_type(
|
||||||
state,
|
state,
|
||||||
block.body.voluntary_exits,
|
block.body.voluntary_exits,
|
||||||
spec.MAX_VOLUNTARY_EXITS,
|
spec.MAX_VOLUNTARY_EXITS,
|
||||||
|
@ -69,7 +69,7 @@ def process_transactions(state: BeaconState, block: BeaconBlock) -> None:
|
||||||
)
|
)
|
||||||
|
|
||||||
assert len(block.body.transfers) == len(set(block.body.transfers))
|
assert len(block.body.transfers) == len(set(block.body.transfers))
|
||||||
process_transaction_type(
|
process_operation_type(
|
||||||
state,
|
state,
|
||||||
block.body.transfers,
|
block.body.transfers,
|
||||||
spec.MAX_TRANSFERS,
|
spec.MAX_TRANSFERS,
|
||||||
|
@ -84,7 +84,7 @@ def process_block(state: BeaconState,
|
||||||
spec.process_randao(state, block)
|
spec.process_randao(state, block)
|
||||||
spec.process_eth1_data(state, block)
|
spec.process_eth1_data(state, block)
|
||||||
|
|
||||||
process_transactions(state, block)
|
process_operations(state, block)
|
||||||
if verify_state_root:
|
if verify_state_root:
|
||||||
spec.verify_block_state_root(state, block)
|
spec.verify_block_state_root(state, block)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue