Merge branch 'dev' into JustinDrake-patch-19
This commit is contained in:
commit
64e3db09d4
|
@ -61,6 +61,10 @@
|
|||
- [`is_active_validator`](#is_active_validator)
|
||||
- [`is_slashable_validator`](#is_slashable_validator)
|
||||
- [`get_active_validator_indices`](#get_active_validator_indices)
|
||||
- [`get_balance`](#get_balance)
|
||||
- [`set_balance`](#set_balance)
|
||||
- [`increase_balance`](#increase_balance)
|
||||
- [`decrease_balance`](#decrease_balance)
|
||||
- [`get_permuted_index`](#get_permuted_index)
|
||||
- [`get_split_offset`](#get_split_offset)
|
||||
- [`get_epoch_committee_count`](#get_epoch_committee_count)
|
||||
|
@ -116,7 +120,7 @@
|
|||
- [Helper functions](#helper-functions-1)
|
||||
- [Justification](#justification)
|
||||
- [Crosslinks](#crosslinks)
|
||||
- [Eth1 data](#eth1-data-1)
|
||||
- [Eth1 data](#eth1-data)
|
||||
- [Rewards and penalties](#rewards-and-penalties)
|
||||
- [Justification and finalization](#justification-and-finalization)
|
||||
- [Crosslinks](#crosslinks-1)
|
||||
|
@ -129,7 +133,7 @@
|
|||
- [Per-block processing](#per-block-processing)
|
||||
- [Block header](#block-header)
|
||||
- [RANDAO](#randao)
|
||||
- [Eth1 data](#eth1-data)
|
||||
- [Eth1 data](#eth1-data-1)
|
||||
- [Transactions](#transactions)
|
||||
- [Proposer slashings](#proposer-slashings)
|
||||
- [Attester slashings](#attester-slashings)
|
||||
|
@ -183,7 +187,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code.
|
|||
| `SHARD_COUNT` | `2**10` (= 1,024) |
|
||||
| `TARGET_COMMITTEE_SIZE` | `2**7` (= 128) |
|
||||
| `MAX_BALANCE_CHURN_QUOTIENT` | `2**5` (= 32) |
|
||||
| `MAX_INDICES_PER_SLASHABLE_VOTE` | `2**12` (= 4,096) |
|
||||
| `MAX_SLASHABLE_ATTESTATION_PARTICIPANTS` | `2**12` (= 4,096) |
|
||||
| `MAX_EXIT_DEQUEUES_PER_EPOCH` | `2**2` (= 4) |
|
||||
| `SHUFFLE_ROUND_COUNT` | 90 |
|
||||
|
||||
|
@ -202,8 +206,8 @@ Code snippets appearing in `this style` are to be interpreted as Python code.
|
|||
| - | - | :-: |
|
||||
| `MIN_DEPOSIT_AMOUNT` | `2**0 * 10**9` (= 1,000,000,000) | Gwei |
|
||||
| `MAX_DEPOSIT_AMOUNT` | `2**5 * 10**9` (= 32,000,000,000) | Gwei |
|
||||
| `FORK_CHOICE_BALANCE_INCREMENT` | `2**0 * 10**9` (= 1,000,000,000) | Gwei |
|
||||
| `EJECTION_BALANCE` | `2**4 * 10**9` (= 16,000,000,000) | Gwei |
|
||||
| `HIGH_BALANCE_INCREMENT` | `2**0 * 10**9` (= 1,000,000,000) | Gwei |
|
||||
|
||||
### Initial values
|
||||
|
||||
|
@ -253,7 +257,7 @@ Code snippets appearing in `this style` are to be interpreted as Python code.
|
|||
| `MIN_PENALTY_QUOTIENT` | `2**5` (= 32) |
|
||||
|
||||
* 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 transactions per block
|
||||
|
@ -417,7 +421,6 @@ The types are defined topologically to aid in facilitating an executable version
|
|||
'signature': 'bytes96',
|
||||
}
|
||||
```
|
||||
|
||||
#### `Validator`
|
||||
|
||||
```python
|
||||
|
@ -436,6 +439,8 @@ The types are defined topologically to aid in facilitating an executable version
|
|||
'initiated_exit': 'bool',
|
||||
# Was the validator slashed
|
||||
'slashed': 'bool',
|
||||
# Rounded balance
|
||||
'high_balance': 'uint64'
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -596,7 +601,7 @@ The types are defined topologically to aid in facilitating an executable version
|
|||
|
||||
# Validator registry
|
||||
'validator_registry': [Validator],
|
||||
'validator_balances': ['uint64'],
|
||||
'balances': ['uint64'],
|
||||
'validator_registry_update_epoch': 'uint64',
|
||||
|
||||
# Randomness and committees
|
||||
|
@ -762,12 +767,45 @@ def get_active_validator_indices(validators: List[Validator], epoch: Epoch) -> L
|
|||
return [i for i, v in enumerate(validators) if is_active_validator(v, epoch)]
|
||||
```
|
||||
|
||||
### `get_balance`
|
||||
|
||||
```python
|
||||
def get_balance(state: BeaconState, index: int) -> int:
|
||||
return state.balances[index]
|
||||
```
|
||||
|
||||
### `set_balance`
|
||||
|
||||
```python
|
||||
def set_balance(state: BeaconState, index: int, balance: int) -> None:
|
||||
validator = state.validator_registry[index]
|
||||
HALF_INCREMENT = HIGH_BALANCE_INCREMENT // 2
|
||||
if validator.high_balance > balance or validator.high_balance + 3 * HALF_INCREMENT < balance:
|
||||
validator.high_balance = balance - balance % HIGH_BALANCE_INCREMENT
|
||||
state.balances[index] = balance
|
||||
```
|
||||
|
||||
### `increase_balance`
|
||||
|
||||
```python
|
||||
def increase_balance(state: BeaconState, index: int, delta: int) -> None:
|
||||
set_balance(state, index, get_balance(state, index) + delta)
|
||||
```
|
||||
|
||||
### `decrease_balance`
|
||||
|
||||
```python
|
||||
def decrease_balance(state: BeaconState, index: int, delta: int) -> None:
|
||||
cur_balance = get_balance(state, index)
|
||||
set_balance(state, index, cur_balance - delta if cur_balance >= delta else 0)
|
||||
```
|
||||
|
||||
### `get_permuted_index`
|
||||
|
||||
```python
|
||||
def get_permuted_index(index: int, list_size: int, seed: Bytes32) -> int:
|
||||
"""
|
||||
Return `p(index)` in a pseudorandom permutation `p` of `0...list_size-1` with ``seed`` as entropy.
|
||||
Return `p(index)` in a pseudorandom permutation `p` of `0...list_size - 1` with ``seed`` as entropy.
|
||||
|
||||
Utilizes 'swap or not' shuffling found in
|
||||
https://link.springer.com/content/pdf/10.1007%2F978-3-642-32009-5_1.pdf
|
||||
|
@ -791,8 +829,12 @@ def get_permuted_index(index: int, list_size: int, seed: Bytes32) -> int:
|
|||
### `get_split_offset`
|
||||
|
||||
```python
|
||||
def get_split_offset(list_length: int, split_count: int, index: int) -> int:
|
||||
return (list_length * index) // split_count
|
||||
def get_split_offset(list_size: int, chunks: int, index: int) -> int:
|
||||
"""
|
||||
Returns a value such that for a list L, chunk count k and index i,
|
||||
split(L, k)[i] == L[get_split_offset(len(L), k, i): get_split_offset(len(L), k, i+1)]
|
||||
"""
|
||||
return (list_size * index) // chunks
|
||||
```
|
||||
|
||||
### `get_epoch_committee_count`
|
||||
|
@ -1091,7 +1133,7 @@ def get_effective_balance(state: BeaconState, index: ValidatorIndex) -> Gwei:
|
|||
"""
|
||||
Return the effective balance (also known as "balance at stake") for a validator with the given ``index``.
|
||||
"""
|
||||
return min(state.validator_balances[index], MAX_DEPOSIT_AMOUNT)
|
||||
return min(get_balance(state, index), MAX_DEPOSIT_AMOUNT)
|
||||
```
|
||||
|
||||
### `get_total_balance`
|
||||
|
@ -1168,7 +1210,7 @@ def verify_slashable_attestation(state: BeaconState, slashable_attestation: Slas
|
|||
if slashable_attestation.custody_bitfield != b'\x00' * len(slashable_attestation.custody_bitfield): # [TO BE REMOVED IN PHASE 1]
|
||||
return False
|
||||
|
||||
if len(slashable_attestation.validator_indices) == 0:
|
||||
if not (1 <= len(slashable_attestation.validator_indices) <= MAX_SLASHABLE_ATTESTATION_PARTICIPANTS):
|
||||
return False
|
||||
|
||||
for i in range(len(slashable_attestation.validator_indices) - 1):
|
||||
|
@ -1178,9 +1220,6 @@ def verify_slashable_attestation(state: BeaconState, slashable_attestation: Slas
|
|||
if not verify_bitfield(slashable_attestation.custody_bitfield, len(slashable_attestation.validator_indices)):
|
||||
return False
|
||||
|
||||
if len(slashable_attestation.validator_indices) > MAX_INDICES_PER_SLASHABLE_VOTE:
|
||||
return False
|
||||
|
||||
custody_bit_0_indices = []
|
||||
custody_bit_1_indices = []
|
||||
for i, validator_index in enumerate(slashable_attestation.validator_indices):
|
||||
|
@ -1335,14 +1374,17 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None:
|
|||
withdrawable_epoch=FAR_FUTURE_EPOCH,
|
||||
initiated_exit=False,
|
||||
slashed=False,
|
||||
high_balance=0
|
||||
)
|
||||
|
||||
# Note: In phase 2 registry indices that have been withdrawn for a long time will be recycled.
|
||||
state.validator_registry.append(validator)
|
||||
state.validator_balances.append(amount)
|
||||
state.balances.append(0)
|
||||
set_balance(state, len(state.validator_registry) - 1, amount)
|
||||
else:
|
||||
# Increase balance by deposit amount
|
||||
state.validator_balances[validator_pubkeys.index(pubkey)] += amount
|
||||
index = validator_pubkeys.index(pubkey)
|
||||
increase_balance(state, index, amount)
|
||||
```
|
||||
|
||||
### Routines for updating validator status
|
||||
|
@ -1403,8 +1445,8 @@ def slash_validator(state: BeaconState, index: ValidatorIndex) -> None:
|
|||
|
||||
whistleblower_index = get_beacon_proposer_index(state, state.slot)
|
||||
whistleblower_reward = get_effective_balance(state, index) // WHISTLEBLOWER_REWARD_QUOTIENT
|
||||
state.validator_balances[whistleblower_index] += whistleblower_reward
|
||||
state.validator_balances[index] -= whistleblower_reward
|
||||
increase_balance(state, whistleblower_index, whistleblower_reward)
|
||||
decrease_balance(state, index, whistleblower_reward)
|
||||
validator.slashed = True
|
||||
validator.withdrawable_epoch = get_current_epoch(state) + LATEST_SLASHED_EXIT_LENGTH
|
||||
```
|
||||
|
@ -1525,7 +1567,7 @@ def get_genesis_beacon_state(genesis_validator_deposits: List[Deposit],
|
|||
|
||||
# Validator registry
|
||||
validator_registry=[],
|
||||
validator_balances=[],
|
||||
balances=[],
|
||||
validator_registry_update_epoch=GENESIS_EPOCH,
|
||||
|
||||
# Randomness and committees
|
||||
|
@ -1640,9 +1682,12 @@ def lmd_ghost(store: Store, start_state: BeaconState, start_block: BeaconBlock)
|
|||
for validator_index in active_validator_indices
|
||||
]
|
||||
|
||||
# Use the rounded-balance-with-hysteresis supplied by the protocol for fork
|
||||
# choice voting. This reduces the number of recomputations that need to be
|
||||
# made for optimized implementations that precompute and save data
|
||||
def get_vote_count(block: BeaconBlock) -> int:
|
||||
return sum(
|
||||
get_effective_balance(start_state.validator_balances[validator_index]) // FORK_CHOICE_BALANCE_INCREMENT
|
||||
start_state.validator_registry[validator_index].high_balance
|
||||
for validator_index, target in attestation_targets
|
||||
if get_ancestor(store, target, block.slot) == block
|
||||
)
|
||||
|
@ -2033,10 +2078,10 @@ def apply_rewards(state: BeaconState) -> None:
|
|||
deltas1 = get_justification_and_finalization_deltas(state)
|
||||
deltas2 = get_crosslink_deltas(state)
|
||||
for i in range(len(state.validator_registry)):
|
||||
state.validator_balances[i] = max(
|
||||
set_balance(state, i, max(
|
||||
0,
|
||||
state.validator_balances[i] + deltas1[0][i] + deltas2[0][i] - deltas1[1][i] - deltas2[1][i]
|
||||
)
|
||||
get_balance(state, i) + deltas1[0][i] + deltas2[0][i] - deltas1[1][i] - deltas2[1][i]
|
||||
))
|
||||
```
|
||||
|
||||
#### Ejections
|
||||
|
@ -2050,7 +2095,7 @@ def process_ejections(state: BeaconState) -> None:
|
|||
and eject active validators with balance below ``EJECTION_BALANCE``.
|
||||
"""
|
||||
for index in get_active_validator_indices(state.validator_registry, get_current_epoch(state)):
|
||||
if state.validator_balances[index] < EJECTION_BALANCE:
|
||||
if get_balance(state, index) < EJECTION_BALANCE:
|
||||
initiate_validator_exit(state, index)
|
||||
```
|
||||
|
||||
|
@ -2093,7 +2138,7 @@ def update_validator_registry(state: BeaconState) -> None:
|
|||
# Activate validators within the allowable balance churn
|
||||
balance_churn = 0
|
||||
for index, validator in enumerate(state.validator_registry):
|
||||
if validator.activation_epoch == FAR_FUTURE_EPOCH and state.validator_balances[index] >= MAX_DEPOSIT_AMOUNT:
|
||||
if validator.activation_epoch == FAR_FUTURE_EPOCH and get_balance(state, index) >= MAX_DEPOSIT_AMOUNT:
|
||||
# Check the balance churn would be within the allowance
|
||||
balance_churn += get_effective_balance(state, index)
|
||||
if balance_churn > max_balance_churn:
|
||||
|
@ -2178,7 +2223,7 @@ def process_slashings(state: BeaconState) -> None:
|
|||
get_effective_balance(state, index) * min(total_penalties * 3, total_balance) // total_balance,
|
||||
get_effective_balance(state, index) // MIN_PENALTY_QUOTIENT
|
||||
)
|
||||
state.validator_balances[index] -= penalty
|
||||
decrease_balance(state, index, penalty)
|
||||
```
|
||||
|
||||
```python
|
||||
|
@ -2484,12 +2529,12 @@ def process_transfer(state: BeaconState, transfer: Transfer) -> None:
|
|||
Note that this function mutates ``state``.
|
||||
"""
|
||||
# Verify the amount and fee aren't individually too big (for anti-overflow purposes)
|
||||
assert state.validator_balances[transfer.sender] >= max(transfer.amount, transfer.fee)
|
||||
assert get_balance(state, transfer.sender) >= max(transfer.amount, transfer.fee)
|
||||
# Verify that we have enough ETH to send, and that after the transfer the balance will be either
|
||||
# exactly zero or at least MIN_DEPOSIT_AMOUNT
|
||||
assert (
|
||||
state.validator_balances[transfer.sender] == transfer.amount + transfer.fee or
|
||||
state.validator_balances[transfer.sender] >= transfer.amount + transfer.fee + MIN_DEPOSIT_AMOUNT
|
||||
get_balance(state, transfer.sender) == transfer.amount + transfer.fee or
|
||||
get_balance(state, transfer.sender) >= transfer.amount + transfer.fee + MIN_DEPOSIT_AMOUNT
|
||||
)
|
||||
# A transfer is valid in only one slot
|
||||
assert state.slot == transfer.slot
|
||||
|
@ -2511,9 +2556,9 @@ def process_transfer(state: BeaconState, transfer: Transfer) -> None:
|
|||
domain=get_domain(state.fork, slot_to_epoch(transfer.slot), DOMAIN_TRANSFER)
|
||||
)
|
||||
# Process the transfer
|
||||
state.validator_balances[transfer.sender] -= transfer.amount + transfer.fee
|
||||
state.validator_balances[transfer.recipient] += transfer.amount
|
||||
state.validator_balances[get_beacon_proposer_index(state, state.slot)] += transfer.fee
|
||||
decrease_balance(state, transfer.sender, transfer.amount + transfer.fee)
|
||||
increase_balance(state, transfer.recipient, transfer.amount)
|
||||
increase_balance(state, get_beacon_proposer_index(state, state.slot), transfer.fee)
|
||||
```
|
||||
|
||||
#### State root verification
|
||||
|
|
|
@ -19,7 +19,6 @@ At the current stage, Phase 1, while fundamentally feature-complete, is still su
|
|||
- [Signature domains](#signature-domains)
|
||||
- [Shard chains and crosslink data](#shard-chains-and-crosslink-data)
|
||||
- [Helper functions](#helper-functions)
|
||||
- [`get_split_offset`](#get_split_offset)
|
||||
- [`get_shuffled_committee`](#get_shuffled_committee)
|
||||
- [`get_persistent_committee`](#get_persistent_committee)
|
||||
- [`get_shard_proposer_index`](#get_shard_proposer_index)
|
||||
|
@ -122,17 +121,6 @@ Phase 1 depends upon all of the constants defined in [Phase 0](0_beacon-chain.md
|
|||
|
||||
## Helper functions
|
||||
|
||||
#### `get_split_offset`
|
||||
|
||||
````python
|
||||
def get_split_offset(list_size: int, chunks: int, index: int) -> int:
|
||||
"""
|
||||
Returns a value such that for a list L, chunk count k and index i,
|
||||
split(L, k)[i] == L[get_split_offset(len(L), k, i): get_split_offset(len(L), k, i+1)]
|
||||
"""
|
||||
return (list_size * index) // chunks
|
||||
````
|
||||
|
||||
#### `get_shuffled_committee`
|
||||
|
||||
```python
|
||||
|
|
|
@ -4,6 +4,8 @@ import pytest
|
|||
|
||||
from build.phase0.spec import (
|
||||
get_beacon_proposer_index,
|
||||
cache_state,
|
||||
advance_slot,
|
||||
process_block_header,
|
||||
)
|
||||
from tests.phase0.helpers import (
|
||||
|
@ -14,13 +16,56 @@ from tests.phase0.helpers import (
|
|||
pytestmark = pytest.mark.header
|
||||
|
||||
|
||||
def prepare_state_for_header_processing(state):
|
||||
cache_state(state)
|
||||
advance_slot(state)
|
||||
|
||||
|
||||
def run_block_header_processing(state, block, valid=True):
|
||||
"""
|
||||
Run ``process_block_header`` returning the pre and post state.
|
||||
If ``valid == False``, run expecting ``AssertionError``
|
||||
"""
|
||||
prepare_state_for_header_processing(state)
|
||||
post_state = deepcopy(state)
|
||||
|
||||
if not valid:
|
||||
with pytest.raises(AssertionError):
|
||||
process_block_header(post_state, block)
|
||||
return state, None
|
||||
|
||||
process_block_header(post_state, block)
|
||||
return state, post_state
|
||||
|
||||
|
||||
def test_success(state):
|
||||
block = build_empty_block_for_next_slot(state)
|
||||
pre_state, post_state = run_block_header_processing(state, block)
|
||||
return state, block, post_state
|
||||
|
||||
|
||||
def test_invalid_slot(state):
|
||||
block = build_empty_block_for_next_slot(state)
|
||||
block.slot = state.slot + 2 # invalid slot
|
||||
|
||||
pre_state, post_state = run_block_header_processing(state, block, valid=False)
|
||||
return pre_state, block, None
|
||||
|
||||
|
||||
def test_invalid_previous_block_root(state):
|
||||
block = build_empty_block_for_next_slot(state)
|
||||
block.previous_block_root = b'\12'*32 # invalid prev root
|
||||
|
||||
pre_state, post_state = run_block_header_processing(state, block, valid=False)
|
||||
return pre_state, block, None
|
||||
|
||||
|
||||
def test_proposer_slashed(state):
|
||||
pre_state = deepcopy(state)
|
||||
# set proposer to slashed
|
||||
proposer_index = get_beacon_proposer_index(state, state.slot + 1)
|
||||
state.validator_registry[proposer_index].slashed = True
|
||||
|
||||
block = build_empty_block_for_next_slot(pre_state)
|
||||
proposer_index = get_beacon_proposer_index(pre_state, block.slot)
|
||||
pre_state.validator_registry[proposer_index].slashed = True
|
||||
with pytest.raises(AssertionError):
|
||||
process_block_header(pre_state, block)
|
||||
block = build_empty_block_for_next_slot(state)
|
||||
|
||||
return state, [block], None
|
||||
pre_state, post_state = run_block_header_processing(state, block, valid=False)
|
||||
return pre_state, block, None
|
||||
|
|
|
@ -5,6 +5,7 @@ import build.phase0.spec as spec
|
|||
|
||||
from build.phase0.spec import (
|
||||
Deposit,
|
||||
get_balance,
|
||||
process_deposit,
|
||||
)
|
||||
from tests.phase0.helpers import (
|
||||
|
@ -38,8 +39,9 @@ def test_success(state, deposit_data_leaves, pubkeys, privkeys):
|
|||
process_deposit(post_state, deposit)
|
||||
|
||||
assert len(post_state.validator_registry) == len(state.validator_registry) + 1
|
||||
assert len(post_state.validator_balances) == len(state.validator_balances) + 1
|
||||
assert len(post_state.balances) == len(state.balances) + 1
|
||||
assert post_state.validator_registry[index].pubkey == pubkeys[index]
|
||||
assert get_balance(post_state, index) == spec.MAX_DEPOSIT_AMOUNT
|
||||
assert post_state.deposit_index == post_state.latest_eth1_data.deposit_count
|
||||
|
||||
return pre_state, deposit, post_state
|
||||
|
@ -62,16 +64,16 @@ def test_success_top_up(state, deposit_data_leaves, pubkeys, privkeys):
|
|||
|
||||
pre_state.latest_eth1_data.deposit_root = root
|
||||
pre_state.latest_eth1_data.deposit_count = len(deposit_data_leaves)
|
||||
pre_balance = pre_state.validator_balances[validator_index]
|
||||
pre_balance = get_balance(pre_state, validator_index)
|
||||
|
||||
post_state = deepcopy(pre_state)
|
||||
|
||||
process_deposit(post_state, deposit)
|
||||
|
||||
assert len(post_state.validator_registry) == len(state.validator_registry)
|
||||
assert len(post_state.validator_balances) == len(state.validator_balances)
|
||||
assert len(post_state.balances) == len(state.balances)
|
||||
assert post_state.deposit_index == post_state.latest_eth1_data.deposit_count
|
||||
assert post_state.validator_balances[validator_index] == pre_balance + amount
|
||||
assert get_balance(post_state, validator_index) == pre_balance + amount
|
||||
|
||||
return pre_state, deposit, post_state
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ from build.phase0.spec import (
|
|||
# functions
|
||||
get_active_validator_indices,
|
||||
get_attestation_participants,
|
||||
get_balance,
|
||||
get_block_root,
|
||||
get_crosslink_committees_at_slot,
|
||||
get_current_epoch,
|
||||
|
@ -28,6 +29,7 @@ from build.phase0.spec import (
|
|||
get_state_root,
|
||||
advance_slot,
|
||||
cache_state,
|
||||
set_balance,
|
||||
verify_merkle_branch,
|
||||
hash,
|
||||
)
|
||||
|
@ -168,7 +170,7 @@ def test_proposer_slashing(state, pubkeys, privkeys):
|
|||
assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||
assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
|
||||
# lost whistleblower reward
|
||||
assert test_state.validator_balances[validator_index] < state.validator_balances[validator_index]
|
||||
assert get_balance(test_state, validator_index) < get_balance(state, validator_index)
|
||||
|
||||
return state, [block], test_state
|
||||
|
||||
|
@ -203,7 +205,8 @@ def test_deposit_in_block(state, deposit_data_leaves, pubkeys, privkeys):
|
|||
|
||||
state_transition(post_state, block)
|
||||
assert len(post_state.validator_registry) == len(state.validator_registry) + 1
|
||||
assert len(post_state.validator_balances) == len(state.validator_balances) + 1
|
||||
assert len(post_state.balances) == len(state.balances) + 1
|
||||
assert get_balance(post_state, index) == spec.MAX_DEPOSIT_AMOUNT
|
||||
assert post_state.validator_registry[index].pubkey == pubkeys[index]
|
||||
|
||||
return pre_state, [block], post_state
|
||||
|
@ -238,12 +241,12 @@ def test_deposit_top_up(state, pubkeys, privkeys, deposit_data_leaves):
|
|||
block = build_empty_block_for_next_slot(pre_state)
|
||||
block.body.deposits.append(deposit)
|
||||
|
||||
pre_balance = pre_state.validator_balances[validator_index]
|
||||
pre_balance = get_balance(pre_state, validator_index)
|
||||
post_state = deepcopy(pre_state)
|
||||
state_transition(post_state, block)
|
||||
assert len(post_state.validator_registry) == len(pre_state.validator_registry)
|
||||
assert len(post_state.validator_balances) == len(pre_state.validator_balances)
|
||||
assert post_state.validator_balances[validator_index] == pre_balance + amount
|
||||
assert len(post_state.balances) == len(pre_state.balances)
|
||||
assert get_balance(post_state, validator_index) == pre_balance + amount
|
||||
|
||||
return pre_state, [block], post_state
|
||||
|
||||
|
@ -412,8 +415,8 @@ def test_transfer(state, pubkeys, privkeys):
|
|||
recipient_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0]
|
||||
transfer_pubkey = pubkeys[-1]
|
||||
transfer_privkey = privkeys[-1]
|
||||
amount = pre_state.validator_balances[sender_index]
|
||||
pre_transfer_recipient_balance = pre_state.validator_balances[recipient_index]
|
||||
amount = get_balance(pre_state, sender_index)
|
||||
pre_transfer_recipient_balance = get_balance(pre_state, recipient_index)
|
||||
transfer = Transfer(
|
||||
sender=sender_index,
|
||||
recipient=recipient_index,
|
||||
|
@ -448,8 +451,8 @@ def test_transfer(state, pubkeys, privkeys):
|
|||
block.body.transfers.append(transfer)
|
||||
state_transition(post_state, block)
|
||||
|
||||
sender_balance = post_state.validator_balances[sender_index]
|
||||
recipient_balance = post_state.validator_balances[recipient_index]
|
||||
sender_balance = get_balance(post_state, sender_index)
|
||||
recipient_balance = get_balance(post_state, recipient_index)
|
||||
assert sender_balance == 0
|
||||
assert recipient_balance == pre_transfer_recipient_balance + amount
|
||||
|
||||
|
@ -465,7 +468,7 @@ def test_ejection(state):
|
|||
assert pre_state.validator_registry[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH
|
||||
|
||||
# set validator balance to below ejection threshold
|
||||
pre_state.validator_balances[validator_index] = spec.EJECTION_BALANCE - 1
|
||||
set_balance(pre_state, validator_index, spec.EJECTION_BALANCE - 1)
|
||||
|
||||
post_state = deepcopy(pre_state)
|
||||
#
|
||||
|
|
Loading…
Reference in New Issue