Phase 1 block tests are working
This commit is contained in:
parent
ab2ee0e2c2
commit
2449db1bb6
|
@ -111,7 +111,7 @@ Configuration is not namespaced. Instead it is strictly an extension;
|
|||
| `DOMAIN_LIGHT_CLIENT` | `DomainType('0x82000000')` | |
|
||||
| `MAX_CUSTODY_CHUNK_CHALLENGE_RECORDS` | `2**20` (= 1,048,576) |
|
||||
| `BYTES_PER_CUSTODY_CHUNK` | `2**12` | bytes |
|
||||
| `MAX_CUSTODY_RESPONSE_DEPTH` | `ceillog2(MAX_SHARD_BLOCK_SIZE // BYTES_PER_CUSTODY_CHUNK) | - | - |
|
||||
| `CUSTODY_RESPONSE_DEPTH` | `ceillog2(MAX_SHARD_BLOCK_SIZE // BYTES_PER_CUSTODY_CHUNK) | - | - |
|
||||
|
||||
|
||||
|
||||
|
@ -137,7 +137,6 @@ class CustodyChunkChallengeRecord(Container):
|
|||
responder_index: ValidatorIndex
|
||||
inclusion_epoch: Epoch
|
||||
data_root: Root
|
||||
depth: uint64
|
||||
chunk_index: uint64
|
||||
```
|
||||
|
||||
|
@ -148,7 +147,7 @@ class CustodyChunkResponse(Container):
|
|||
challenge_index: uint64
|
||||
chunk_index: uint64
|
||||
chunk: ByteVector[BYTES_PER_CUSTODY_CHUNK]
|
||||
branch: List[Root, MAX_CUSTODY_RESPONSE_DEPTH]
|
||||
branch: Vector[Root, CUSTODY_RESPONSE_DEPTH]
|
||||
```
|
||||
|
||||
#### `CustodySlashing`
|
||||
|
@ -281,7 +280,8 @@ class Validator(Container):
|
|||
# (of the particular validator) in which the validator is activated
|
||||
# = get_custody_period_for_validator(...)
|
||||
next_custody_secret_to_reveal: uint64
|
||||
max_reveal_lateness: Epoch
|
||||
# TODO: The max_reveal_lateness doesn't really make sense anymore.
|
||||
# So how do we incentivise early custody key reveals now?
|
||||
```
|
||||
|
||||
### Extended `BeaconBlockBody`
|
||||
|
@ -428,6 +428,7 @@ class ShardTransition(Container):
|
|||
# Shard block lengths
|
||||
shard_block_lengths: List[uint64, MAX_SHARD_BLOCKS_PER_ATTESTATION]
|
||||
# Shard data roots
|
||||
# The root is of ByteVector[MAX_]
|
||||
shard_data_roots: List[Bytes32, MAX_SHARD_BLOCKS_PER_ATTESTATION]
|
||||
# Intermediate shard states
|
||||
shard_states: List[ShardState, MAX_SHARD_BLOCKS_PER_ATTESTATION]
|
||||
|
|
|
@ -17,11 +17,6 @@
|
|||
- [Reward and penalty quotients](#reward-and-penalty-quotients)
|
||||
- [Signature domain types](#signature-domain-types)
|
||||
- [Data structures](#data-structures)
|
||||
- [New Beacon Chain operations](#new-beacon-chain-operations)
|
||||
- [`CustodySlashing`](#custodyslashing)
|
||||
- [`SignedCustodySlashing`](#signedcustodyslashing)
|
||||
- [`CustodyKeyReveal`](#custodykeyreveal)
|
||||
- [`EarlyDerivedSecretReveal`](#earlyderivedsecretreveal)
|
||||
- [Helpers](#helpers)
|
||||
- [`legendre_bit`](#legendre_bit)
|
||||
- [`get_custody_atoms`](#get_custody_atoms)
|
||||
|
@ -64,7 +59,6 @@ This document details the beacon chain additions and changes in Phase 1 of Ether
|
|||
| `EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS` | `2**14` (= 16,384) | epochs | ~73 days |
|
||||
| `EPOCHS_PER_CUSTODY_PERIOD` | `2**11` (= 2,048) | epochs | ~9 days |
|
||||
| `CUSTODY_PERIOD_TO_RANDAO_PADDING` | `2**11` (= 2,048) | epochs | ~9 days |
|
||||
| `MAX_REVEAL_LATENESS_DECREMENT` | `2**7` (= 128) | epochs | ~14 hours |
|
||||
| `CHUNK_RESPONSE_DEADLINE` | `2**14` (= 16,384) | epochs | ~73 days |
|
||||
| `MAX_CHUNK_CHALLENGE_DELAY` | `2**11` (= 16,384) | epochs | ~9 days |
|
||||
| `CUSTODY_RESPONSE_DEADLINE` | `2**14` (= 16,384) | epochs | ~73 days |
|
||||
|
@ -168,7 +162,7 @@ def get_custody_secrets(key: BLSSignature) -> Sequence[int]:
|
|||
### `compute_custody_bit`
|
||||
|
||||
```python
|
||||
def compute_custody_bit(key: BLSSignature, data: bytes) -> bit:
|
||||
def compute_custody_bit(key: BLSSignature, data: ByteList[MAX_SHARD_BLOCK_SIZE]) -> bit:
|
||||
secrets = get_custody_secrets(key)
|
||||
custody_atoms = get_custody_atoms(data)
|
||||
n = len(custody_atoms)
|
||||
|
@ -243,7 +237,6 @@ def process_chunk_challenge(state: BeaconState, challenge: CustodyChunkChallenge
|
|||
)
|
||||
# Verify depth
|
||||
transition_chunks = (challenge.shard_transition.shard_block_lengths[challenge.data_index] + BYTES_PER_CUSTODY_CHUNK - 1) // BYTES_PER_CUSTODY_CHUNK
|
||||
depth = ceillog2(transition_chunks)
|
||||
assert challenge.chunk_index < transition_chunks
|
||||
# Add new chunk challenge record
|
||||
new_record = CustodyChunkChallengeRecord(
|
||||
|
@ -252,7 +245,6 @@ def process_chunk_challenge(state: BeaconState, challenge: CustodyChunkChallenge
|
|||
responder_index=challenge.responder_index,
|
||||
inclusion_epoch=get_current_epoch(state),
|
||||
data_root=challenge.shard_transition.shard_data_roots[challenge.data_index],
|
||||
depth=depth,
|
||||
chunk_index=challenge.chunk_index,
|
||||
)
|
||||
replace_empty_or_append(state.custody_chunk_challenge_records, new_record)
|
||||
|
@ -277,7 +269,7 @@ def process_chunk_challenge_response(state: BeaconState,
|
|||
assert is_valid_merkle_branch(
|
||||
leaf=hash_tree_root(response.chunk),
|
||||
branch=response.branch,
|
||||
depth=challenge.depth,
|
||||
depth=CUSTODY_RESPONSE_DEPTH,
|
||||
index=response.chunk_index,
|
||||
root=challenge.data_root,
|
||||
)
|
||||
|
@ -311,18 +303,6 @@ def process_custody_key_reveal(state: BeaconState, reveal: CustodyKeyReveal) ->
|
|||
signing_root = compute_signing_root(epoch_to_sign, domain)
|
||||
assert bls.Verify(revealer.pubkey, signing_root, reveal.reveal)
|
||||
|
||||
# Decrement max reveal lateness if response is timely
|
||||
if epoch_to_sign + EPOCHS_PER_CUSTODY_PERIOD >= get_current_epoch(state):
|
||||
if revealer.max_reveal_lateness >= MAX_REVEAL_LATENESS_DECREMENT:
|
||||
revealer.max_reveal_lateness -= MAX_REVEAL_LATENESS_DECREMENT
|
||||
else:
|
||||
revealer.max_reveal_lateness = 0
|
||||
else:
|
||||
revealer.max_reveal_lateness = max(
|
||||
revealer.max_reveal_lateness,
|
||||
get_current_epoch(state) - epoch_to_sign - EPOCHS_PER_CUSTODY_PERIOD
|
||||
)
|
||||
|
||||
# Process reveal
|
||||
revealer.next_custody_secret_to_reveal += 1
|
||||
|
||||
|
@ -417,13 +397,15 @@ def process_custody_slashing(state: BeaconState, signed_custody_slashing: Signed
|
|||
assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation))
|
||||
|
||||
# TODO: custody_slashing.data is not chunked like shard blocks yet, result is lots of padding.
|
||||
# ??? What does this mean?
|
||||
|
||||
# TODO: can do a single combined merkle proof of data being attested.
|
||||
# Verify the shard transition is indeed attested by the attestation
|
||||
shard_transition = custody_slashing.shard_transition
|
||||
assert hash_tree_root(shard_transition) == attestation.shard_transition_root
|
||||
assert hash_tree_root(shard_transition) == attestation.data.shard_transition_root
|
||||
# Verify that the provided data matches the shard-transition
|
||||
assert hash_tree_root(custody_slashing.data) == shard_transition.shard_data_roots[custody_slashing.data_index]
|
||||
assert custody_slashing.data.get_backing().get_left().merkle_root() == shard_transition.shard_data_roots[custody_slashing.data_index]
|
||||
assert len(custody_slashing.data) == shard_transition.shard_block_lengths[custody_slashing.data_index]
|
||||
|
||||
# Verify existence and participation of claimed malefactor
|
||||
attesters = get_attesting_indices(state, attestation.data, attestation.aggregation_bits)
|
||||
|
|
|
@ -6,6 +6,8 @@ from eth2spec.test.helpers.block import build_empty_block_for_next_slot
|
|||
from eth2spec.test.helpers.keys import privkeys
|
||||
from eth2spec.utils import bls
|
||||
from eth2spec.utils.ssz.ssz_typing import Bitlist
|
||||
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
|
||||
from eth2spec.test.helpers.custody import get_custody_test_vector
|
||||
|
||||
|
||||
def run_attestation_processing(spec, state, attestation, valid=True):
|
||||
|
@ -72,17 +74,43 @@ def build_attestation_data(spec, state, slot, index, shard_transition_root=None)
|
|||
beacon_block_root=block_root,
|
||||
source=spec.Checkpoint(epoch=source_epoch, root=source_root),
|
||||
target=spec.Checkpoint(epoch=spec.compute_epoch_at_slot(slot), root=epoch_boundary_root),
|
||||
shard_transition_root=shard_transition_root,
|
||||
shard_transition_root=shard_transition_root if shard_transition_root else spec.Root(),
|
||||
)
|
||||
|
||||
|
||||
def convert_to_valid_on_time_attestation(spec, state, attestation, signed=False):
|
||||
def convert_to_valid_on_time_attestation(spec, state, attestation, signed=False, shard_transition=None, valid_custody_bits=None):
|
||||
shard = spec.get_shard(state, attestation)
|
||||
offset_slots = spec.compute_offset_slots(spec.get_latest_slot_for_shard(state, shard), state.slot + 1)
|
||||
for offset_slot in offset_slots:
|
||||
|
||||
if valid_custody_bits is not None:
|
||||
beacon_committee = spec.get_beacon_committee(
|
||||
state,
|
||||
attestation.data.slot,
|
||||
attestation.data.index,
|
||||
)
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
custody_secrets = [None for i in beacon_committee]
|
||||
for i in range(len(beacon_committee)):
|
||||
validator = state.validators[beacon_committee[i]]
|
||||
|
||||
period = spec.get_custody_period_for_validator(beacon_committee[i], attestation.data.target.epoch)
|
||||
|
||||
epoch_to_sign = spec.get_randao_epoch_for_custody_period(period, beacon_committee[i])
|
||||
|
||||
domain = spec.get_domain(state, spec.DOMAIN_RANDAO, epoch_to_sign)
|
||||
signing_root = spec.compute_signing_root(spec.Epoch(epoch_to_sign), domain)
|
||||
custody_secrets[i] = bls.Sign(privkeys[beacon_committee[i]], signing_root)
|
||||
|
||||
|
||||
for i, offset_slot in enumerate(offset_slots):
|
||||
attestation.custody_bits_blocks.append(
|
||||
Bitlist[spec.MAX_VALIDATORS_PER_COMMITTEE]([0 for _ in attestation.aggregation_bits])
|
||||
)
|
||||
if valid_custody_bits is not None:
|
||||
test_vector = get_custody_test_vector(shard_transition.shard_block_lengths[i])
|
||||
for j in range(len(attestation.custody_bits_blocks[i])):
|
||||
if attestation.aggregation_bits[j]:
|
||||
attestation.custody_bits_blocks[i][j] = spec.compute_custody_bit(custody_secrets[j], test_vector) ^ (not valid_custody_bits)
|
||||
|
||||
if signed:
|
||||
sign_attestation(spec, state, attestation)
|
||||
|
@ -90,7 +118,7 @@ def convert_to_valid_on_time_attestation(spec, state, attestation, signed=False)
|
|||
return attestation
|
||||
|
||||
|
||||
def get_valid_on_time_attestation(spec, state, slot=None, index=None, signed=False, shard_transition_root=None):
|
||||
def get_valid_on_time_attestation(spec, state, slot=None, index=None, signed=False, shard_transition=None, valid_custody_bits=None):
|
||||
'''
|
||||
Construct on-time attestation for next slot
|
||||
'''
|
||||
|
@ -99,10 +127,10 @@ def get_valid_on_time_attestation(spec, state, slot=None, index=None, signed=Fal
|
|||
if index is None:
|
||||
index = 0
|
||||
|
||||
return get_valid_attestation(spec, state, slot=slot, index=index, signed=signed, on_time=True, shard_transition_root=shard_transition_root)
|
||||
return get_valid_attestation(spec, state, slot=slot, index=index, signed=signed, on_time=True, shard_transition=shard_transition, valid_custody_bits=valid_custody_bits)
|
||||
|
||||
|
||||
def get_valid_late_attestation(spec, state, slot=None, index=None, signed=False, shard_transition_root=None):
|
||||
def get_valid_late_attestation(spec, state, slot=None, index=None, signed=False, shard_transition=None):
|
||||
'''
|
||||
Construct on-time attestation for next slot
|
||||
'''
|
||||
|
@ -111,16 +139,16 @@ def get_valid_late_attestation(spec, state, slot=None, index=None, signed=False,
|
|||
if index is None:
|
||||
index = 0
|
||||
|
||||
return get_valid_attestation(spec, state, slot=slot, index=index, signed=signed, on_time=False, shard_transition_root=shard_transition_root)
|
||||
return get_valid_attestation(spec, state, slot=slot, index=index, signed=signed, on_time=False, shard_transition=shard_transition)
|
||||
|
||||
|
||||
def get_valid_attestation(spec, state, slot=None, index=None, empty=False, signed=False, on_time=True, shard_transition_root=None):
|
||||
def get_valid_attestation(spec, state, slot=None, index=None, empty=False, signed=False, on_time=True, shard_transition=None, valid_custody_bits=None):
|
||||
if slot is None:
|
||||
slot = state.slot
|
||||
if index is None:
|
||||
index = 0
|
||||
|
||||
attestation_data = build_attestation_data(spec, state, slot, index, shard_transition_root=shard_transition_root)
|
||||
attestation_data = build_attestation_data(spec, state, slot, index, shard_transition_root=hash_tree_root(shard_transition) if shard_transition else spec.Root())
|
||||
|
||||
beacon_committee = spec.get_beacon_committee(
|
||||
state,
|
||||
|
@ -140,7 +168,7 @@ def get_valid_attestation(spec, state, slot=None, index=None, empty=False, signe
|
|||
sign_attestation(spec, state, attestation)
|
||||
|
||||
if spec.fork == 'phase1' and on_time:
|
||||
attestation = convert_to_valid_on_time_attestation(spec, state, attestation, signed)
|
||||
attestation = convert_to_valid_on_time_attestation(spec, state, attestation, signed, shard_transition=shard_transition, valid_custody_bits=valid_custody_bits)
|
||||
|
||||
return attestation
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
from eth2spec.test.helpers.keys import privkeys
|
||||
from eth2spec.utils import bls
|
||||
from eth2spec.utils.ssz.ssz_typing import Bitlist, ByteVector, Bitvector, ByteList
|
||||
from eth2spec.utils.ssz.ssz_typing import Bitlist, ByteVector, Bitvector, ByteList, uint64
|
||||
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
|
||||
from eth2spec.utils.merkle_minimal import get_merkle_root, get_merkle_tree, get_merkle_proof
|
||||
from remerkleable.core import pack_bits_to_chunks
|
||||
from remerkleable.tree import subtree_fill_to_contents, get_depth
|
||||
from remerkleable.tree import subtree_fill_to_contents, get_depth, Node, Gindex, gindex_bit_iter, Root
|
||||
|
||||
BYTES_PER_CHUNK = 32
|
||||
|
||||
|
@ -61,39 +61,45 @@ def bitlist_from_int(max_len, num_bits, n):
|
|||
return Bitlist[max_len](*[(n >> i) & 0b1 for i in range(num_bits)])
|
||||
|
||||
|
||||
def get_valid_custody_slashing(spec, state, attestation, invalid_custody_bit=False):
|
||||
def get_valid_custody_slashing(spec, state, attestation, shard_transition, invalid_custody_bit=False):
|
||||
beacon_committee = spec.get_beacon_committee(
|
||||
state,
|
||||
attestation.data.slot,
|
||||
attestation.data.crosslink.shard,
|
||||
attestation.data.index,
|
||||
)
|
||||
responder_index = beacon_committee[0]
|
||||
challenger_index = beacon_committee[-1]
|
||||
malefactor_index = beacon_committee[0]
|
||||
whistleblower_index = beacon_committee[-1]
|
||||
|
||||
epoch = spec.get_randao_epoch_for_custody_period(attestation.data.target.epoch,
|
||||
responder_index)
|
||||
malefactor_index)
|
||||
|
||||
# Generate the responder key
|
||||
domain = spec.get_domain(state, spec.DOMAIN_RANDAO, epoch)
|
||||
signing_root = spec.compute_signing_root(spec.Epoch(epoch), domain)
|
||||
responder_key = bls.Sign(privkeys[responder_index], signing_root)
|
||||
malefactor_key = bls.Sign(privkeys[malefactor_index], signing_root)
|
||||
data_index = 0
|
||||
data=ByteList[spec.MAX_SHARD_BLOCK_SIZE](get_custody_test_vector(shard_transition.shard_block_lengths[data_index]))
|
||||
print(hash_tree_root(data))
|
||||
print(data.get_backing().get_left().merkle_root())
|
||||
|
||||
chunk_count = spec.get_custody_chunk_count(attestation.data.crosslink)
|
||||
|
||||
chunk_bits = bitlist_from_int(spec.MAX_CUSTODY_CHUNKS, chunk_count, 0)
|
||||
|
||||
n = 0
|
||||
while spec.get_chunk_bits_root(chunk_bits) == attestation.custody_bits[0] ^ invalid_custody_bit:
|
||||
chunk_bits = bitlist_from_int(spec.MAX_CUSTODY_CHUNKS, chunk_count, n)
|
||||
n += 1
|
||||
|
||||
return spec.CustodyBitChallenge(
|
||||
responder_index=responder_index,
|
||||
slashing = spec.CustodySlashing(
|
||||
data_index=data_index,
|
||||
malefactor_index=malefactor_index,
|
||||
malefactor_secret=malefactor_key,
|
||||
whistleblower_index=whistleblower_index,
|
||||
shard_transition=shard_transition,
|
||||
attestation=attestation,
|
||||
challenger_index=challenger_index,
|
||||
responder_key=responder_key,
|
||||
chunk_bits=chunk_bits,
|
||||
data=data,
|
||||
)
|
||||
slashing_domain = spec.get_domain(state, spec.DOMAIN_CUSTODY_BIT_SLASHING)
|
||||
slashing_root = spec.compute_signing_root(slashing, domain)
|
||||
|
||||
signed_slashing = spec.SignedCustodySlashing(
|
||||
message=slashing,
|
||||
signature=bls.Sign(privkeys[whistleblower_index], slashing_root)
|
||||
)
|
||||
|
||||
return signed_slashing
|
||||
|
||||
|
||||
def get_valid_chunk_challenge(spec, state, attestation, shard_transition):
|
||||
|
@ -123,20 +129,35 @@ def custody_chunkify(spec, x):
|
|||
return chunks
|
||||
|
||||
|
||||
def build_proof(anchor, leaf_index):
|
||||
if leaf_index <= 1:
|
||||
return [] # Nothing to prove / invalid index
|
||||
node = anchor
|
||||
proof = []
|
||||
# Walk down, top to bottom to the leaf
|
||||
bit_iter, _ = gindex_bit_iter(leaf_index)
|
||||
for bit in bit_iter:
|
||||
# Always take the opposite hand for the proof.
|
||||
# 1 = right as leaf, thus get left
|
||||
if bit:
|
||||
proof.append(node.get_left().merkle_root())
|
||||
node = node.get_right()
|
||||
else:
|
||||
proof.append(node.get_right().merkle_root())
|
||||
node = node.get_left()
|
||||
|
||||
return list(reversed(proof))
|
||||
|
||||
|
||||
def get_valid_custody_chunk_response(spec, state, chunk_challenge, block_length, challenge_index,
|
||||
invalid_chunk_data=False):
|
||||
custody_data = get_custody_test_vector(block_length)
|
||||
custody_data_block = ByteList[spec.MAX_SHARD_BLOCK_SIZE](custody_data)
|
||||
chunks = custody_chunkify(spec, custody_data)
|
||||
|
||||
chunk_index = chunk_challenge.chunk_index
|
||||
|
||||
chunks_hash_tree_roots = [hash_tree_root(ByteVector[spec.BYTES_PER_CUSTODY_CHUNK](chunk)) for chunk in chunks]
|
||||
chunks_hash_tree_roots += [
|
||||
hash_tree_root(ByteVector[spec.BYTES_PER_CUSTODY_CHUNK](b"\0" * spec.BYTES_PER_CUSTODY_CHUNK))
|
||||
for i in range(2 ** spec.ceillog2(len(chunks)) - len(chunks))]
|
||||
data_tree = get_merkle_tree(chunks_hash_tree_roots)
|
||||
|
||||
data_branch = get_merkle_proof(data_tree, chunk_index)
|
||||
data_branch = build_proof(custody_data_block.get_backing().get_left(), chunk_index + 2**spec.CUSTODY_RESPONSE_DEPTH)
|
||||
|
||||
return spec.CustodyChunkResponse(
|
||||
challenge_index=challenge_index,
|
||||
|
@ -152,7 +173,7 @@ def get_custody_test_vector(bytelength):
|
|||
|
||||
|
||||
def get_shard_transition(spec, start_slot, block_lengths):
|
||||
b = [hash_tree_root(ByteVector[x](get_custody_test_vector(x))) for x in block_lengths]
|
||||
b = [ByteList[spec.MAX_SHARD_BLOCK_SIZE](get_custody_test_vector(x)).get_backing().get_left().merkle_root() for x in block_lengths]
|
||||
shard_transition = spec.ShardTransition(
|
||||
start_slot=start_slot,
|
||||
shard_block_lengths=block_lengths,
|
||||
|
|
|
@ -75,7 +75,7 @@ def test_challenge_appended(spec, state):
|
|||
offset_slots = spec.get_offset_slots(state, shard)
|
||||
shard_transition = get_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots))
|
||||
data_index = 0
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition_root=hash_tree_root(shard_transition))
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition)
|
||||
|
||||
transition_chunks = (shard_transition.shard_block_lengths[data_index] + spec.BYTES_PER_CUSTODY_CHUNK - 1) // spec.BYTES_PER_CUSTODY_CHUNK
|
||||
test_vector = get_custody_test_vector(shard_transition.shard_block_lengths[data_index])
|
||||
|
@ -101,7 +101,7 @@ def test_multiple_epochs_custody(spec, state):
|
|||
offset_slots = spec.get_offset_slots(state, shard)
|
||||
shard_transition = get_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots))
|
||||
data_index = 0
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition_root=hash_tree_root(shard_transition))
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition)
|
||||
|
||||
transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||
|
||||
|
@ -123,7 +123,7 @@ def test_many_epochs_custody(spec, state):
|
|||
offset_slots = spec.get_offset_slots(state, shard)
|
||||
shard_transition = get_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots))
|
||||
data_index = 0
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition_root=hash_tree_root(shard_transition))
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition)
|
||||
|
||||
transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||
|
||||
|
@ -145,7 +145,7 @@ def test_off_chain_attestation(spec, state):
|
|||
offset_slots = spec.get_offset_slots(state, shard)
|
||||
shard_transition = get_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots))
|
||||
data_index = 0
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition_root=hash_tree_root(shard_transition))
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition)
|
||||
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * (spec.EPOCHS_PER_CUSTODY_PERIOD - 1))
|
||||
|
||||
|
@ -163,7 +163,7 @@ def test_custody_response(spec, state):
|
|||
offset_slots = spec.get_offset_slots(state, shard)
|
||||
shard_transition = get_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots))
|
||||
data_index = 0
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition_root=hash_tree_root(shard_transition))
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition)
|
||||
|
||||
transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||
|
||||
|
@ -191,7 +191,7 @@ def test_custody_response_multiple_epochs(spec, state):
|
|||
offset_slots = spec.get_offset_slots(state, shard)
|
||||
shard_transition = get_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots))
|
||||
data_index = 0
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition_root=hash_tree_root(shard_transition))
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition)
|
||||
|
||||
transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||
|
||||
|
@ -219,7 +219,7 @@ def test_custody_response_many_epochs(spec, state):
|
|||
offset_slots = spec.get_offset_slots(state, shard)
|
||||
shard_transition = get_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots))
|
||||
data_index = 0
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition_root=hash_tree_root(shard_transition))
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition)
|
||||
|
||||
transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||
|
||||
|
|
|
@ -28,30 +28,14 @@ def run_custody_key_reveal_processing(spec, state, custody_key_reveal, valid=Tru
|
|||
|
||||
pre_next_custody_secret_to_reveal = \
|
||||
state.validators[revealer_index].next_custody_secret_to_reveal
|
||||
pre_reveal_lateness = state.validators[revealer_index].max_reveal_lateness
|
||||
|
||||
spec.process_custody_key_reveal(state, custody_key_reveal)
|
||||
|
||||
post_next_custody_secret_to_reveal = \
|
||||
state.validators[revealer_index].next_custody_secret_to_reveal
|
||||
post_reveal_lateness = state.validators[revealer_index].max_reveal_lateness
|
||||
|
||||
assert post_next_custody_secret_to_reveal == pre_next_custody_secret_to_reveal + 1
|
||||
|
||||
if spec.get_current_epoch(state) > spec.get_randao_epoch_for_custody_period(
|
||||
pre_next_custody_secret_to_reveal,
|
||||
revealer_index
|
||||
) + spec.EPOCHS_PER_CUSTODY_PERIOD:
|
||||
assert post_reveal_lateness > 0
|
||||
if pre_reveal_lateness == 0:
|
||||
assert post_reveal_lateness == spec.get_current_epoch(state) - spec.get_randao_epoch_for_custody_period(
|
||||
pre_next_custody_secret_to_reveal,
|
||||
revealer_index
|
||||
) - spec.EPOCHS_PER_CUSTODY_PERIOD
|
||||
else:
|
||||
if pre_reveal_lateness > 0:
|
||||
assert post_reveal_lateness < pre_reveal_lateness
|
||||
|
||||
yield 'post', state
|
||||
|
||||
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
from eth2spec.test.helpers.custody import (
|
||||
get_valid_bit_challenge,
|
||||
get_valid_custody_bit_response,
|
||||
get_valid_custody_slashing,
|
||||
get_custody_test_vector,
|
||||
get_custody_merkle_root,
|
||||
get_shard_transition,
|
||||
)
|
||||
from eth2spec.test.helpers.attestations import (
|
||||
get_valid_attestation,
|
||||
get_valid_on_time_attestation,
|
||||
)
|
||||
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
|
||||
from eth2spec.test.helpers.state import next_epoch, get_balance
|
||||
from eth2spec.utils.ssz.ssz_typing import ByteList
|
||||
from eth2spec.test.helpers.state import next_epoch, get_balance, transition_to
|
||||
from eth2spec.test.helpers.block import apply_empty_block
|
||||
from eth2spec.test.context import (
|
||||
with_all_phases_except,
|
||||
|
@ -18,332 +19,174 @@ from eth2spec.test.context import (
|
|||
from eth2spec.test.phase_0.block_processing.test_process_attestation import run_attestation_processing
|
||||
|
||||
|
||||
def run_bit_challenge_processing(spec, state, custody_bit_challenge, valid=True):
|
||||
def run_custody_slashing_processing(spec, state, custody_slashing, valid=True, correct=True):
|
||||
"""
|
||||
Run ``process_bit_challenge``, yielding:
|
||||
- pre-state ('pre')
|
||||
- CustodyBitChallenge ('custody_bit_challenge')
|
||||
- CustodySlashing ('custody_slashing')
|
||||
- post-state ('post').
|
||||
If ``valid == False``, run expecting ``AssertionError``
|
||||
"""
|
||||
yield 'pre', state
|
||||
yield 'custody_bit_challenge', custody_bit_challenge
|
||||
yield 'custody_slashing', custody_slashing
|
||||
|
||||
if not valid:
|
||||
expect_assertion_error(lambda: spec.process_bit_challenge(state, custody_bit_challenge))
|
||||
expect_assertion_error(lambda: spec.process_custody_slashing(state, custody_slashing))
|
||||
yield 'post', None
|
||||
return
|
||||
|
||||
spec.process_bit_challenge(state, custody_bit_challenge)
|
||||
if correct:
|
||||
pre_slashed_balance = get_balance(state, custody_slashing.message.malefactor_index)
|
||||
else:
|
||||
pre_slashed_balance = get_balance(state, custody_slashing.message.whistleblower_index)
|
||||
|
||||
assert state.custody_bit_challenge_records[state.custody_bit_challenge_index - 1].chunk_bits_merkle_root == \
|
||||
hash_tree_root(custody_bit_challenge.chunk_bits)
|
||||
assert state.custody_bit_challenge_records[state.custody_bit_challenge_index - 1].challenger_index == \
|
||||
custody_bit_challenge.challenger_index
|
||||
assert state.custody_bit_challenge_records[state.custody_bit_challenge_index - 1].responder_index == \
|
||||
custody_bit_challenge.responder_index
|
||||
|
||||
yield 'post', state
|
||||
|
||||
|
||||
def run_custody_bit_response_processing(spec, state, custody_response, valid=True):
|
||||
"""
|
||||
Run ``process_bit_challenge_response``, yielding:
|
||||
- pre-state ('pre')
|
||||
- CustodyResponse ('custody_response')
|
||||
- post-state ('post').
|
||||
If ``valid == False``, run expecting ``AssertionError``
|
||||
"""
|
||||
yield 'pre', state
|
||||
yield 'custody_response', custody_response
|
||||
|
||||
if not valid:
|
||||
expect_assertion_error(lambda: spec.process_custody_response(state, custody_response))
|
||||
yield 'post', None
|
||||
return
|
||||
|
||||
challenge = state.custody_bit_challenge_records[custody_response.challenge_index]
|
||||
pre_slashed_balance = get_balance(state, challenge.challenger_index)
|
||||
|
||||
spec.process_custody_response(state, custody_response)
|
||||
|
||||
slashed_validator = state.validators[challenge.challenger_index]
|
||||
spec.process_custody_slashing(state, custody_slashing)
|
||||
|
||||
if correct:
|
||||
slashed_validator = state.validators[custody_slashing.message.malefactor_index]
|
||||
assert get_balance(state, custody_slashing.message.malefactor_index) < pre_slashed_balance
|
||||
else:
|
||||
slashed_validator = state.validators[custody_slashing.message.whistleblower_index]
|
||||
assert get_balance(state, custody_slashing.message.whistleblower_index) < pre_slashed_balance
|
||||
|
||||
assert slashed_validator.slashed
|
||||
assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||
assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
|
||||
|
||||
assert get_balance(state, challenge.challenger_index) < pre_slashed_balance
|
||||
yield 'post', state
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@spec_state_test
|
||||
def test_challenge_appended(spec, state):
|
||||
state.slot = spec.SLOTS_PER_EPOCH
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
def test_custody_slashing(spec, state):
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH)
|
||||
shard = 0
|
||||
offset_slots = spec.get_offset_slots(state, shard)
|
||||
shard_transition = get_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots))
|
||||
data_index = 0
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition, valid_custody_bits=False)
|
||||
|
||||
test_vector = get_custody_test_vector(
|
||||
spec.get_custody_chunk_count(attestation.data.crosslink) * spec.BYTES_PER_CUSTODY_CHUNK)
|
||||
shard_root = get_custody_merkle_root(test_vector)
|
||||
attestation.data.crosslink.data_root = shard_root
|
||||
attestation.custody_bits[0] = 0
|
||||
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||
|
||||
_, _, _ = run_attestation_processing(spec, state, attestation)
|
||||
|
||||
state.slot += spec.SLOTS_PER_EPOCH * spec.EPOCHS_PER_CUSTODY_PERIOD
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * (spec.EPOCHS_PER_CUSTODY_PERIOD - 1))
|
||||
|
||||
challenge = get_valid_bit_challenge(spec, state, attestation)
|
||||
data_index = 0
|
||||
|
||||
yield from run_bit_challenge_processing(spec, state, challenge)
|
||||
slashing = get_valid_custody_slashing(spec, state, attestation, shard_transition)
|
||||
|
||||
yield from run_custody_slashing_processing(spec, state, slashing, correct=True)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@spec_state_test
|
||||
def test_incorrect_custody_slashing(spec, state):
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH)
|
||||
shard = 0
|
||||
offset_slots = spec.get_offset_slots(state, shard)
|
||||
shard_transition = get_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots))
|
||||
data_index = 0
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition, valid_custody_bits=True)
|
||||
|
||||
transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||
|
||||
_, _, _ = run_attestation_processing(spec, state, attestation)
|
||||
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * (spec.EPOCHS_PER_CUSTODY_PERIOD - 1))
|
||||
|
||||
data_index = 0
|
||||
|
||||
slashing = get_valid_custody_slashing(spec, state, attestation, shard_transition)
|
||||
|
||||
yield from run_custody_slashing_processing(spec, state, slashing, correct=False)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@spec_state_test
|
||||
def test_multiple_epochs_custody(spec, state):
|
||||
state.slot = spec.SLOTS_PER_EPOCH * 3
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * 3)
|
||||
shard = 0
|
||||
offset_slots = spec.get_offset_slots(state, shard)
|
||||
shard_transition = get_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots))
|
||||
data_index = 0
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition, valid_custody_bits=False)
|
||||
|
||||
test_vector = get_custody_test_vector(
|
||||
spec.get_custody_chunk_count(attestation.data.crosslink) * spec.BYTES_PER_CUSTODY_CHUNK)
|
||||
shard_root = get_custody_merkle_root(test_vector)
|
||||
attestation.data.crosslink.data_root = shard_root
|
||||
attestation.custody_bits[0] = 0
|
||||
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||
|
||||
_, _, _ = run_attestation_processing(spec, state, attestation)
|
||||
|
||||
state.slot += spec.SLOTS_PER_EPOCH * (spec.EPOCHS_PER_CUSTODY_PERIOD - 1)
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * (spec.EPOCHS_PER_CUSTODY_PERIOD - 1))
|
||||
|
||||
challenge = get_valid_bit_challenge(spec, state, attestation)
|
||||
data_index = 0
|
||||
|
||||
yield from run_bit_challenge_processing(spec, state, challenge)
|
||||
slashing = get_valid_custody_slashing(spec, state, attestation, shard_transition)
|
||||
|
||||
yield from run_custody_slashing_processing(spec, state, slashing, correct=True)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@spec_state_test
|
||||
def test_many_epochs_custody(spec, state):
|
||||
state.slot = spec.SLOTS_PER_EPOCH * 100
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH* 100)
|
||||
shard = 0
|
||||
offset_slots = spec.get_offset_slots(state, shard)
|
||||
shard_transition = get_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots))
|
||||
data_index = 0
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition, valid_custody_bits=False)
|
||||
|
||||
test_vector = get_custody_test_vector(
|
||||
spec.get_custody_chunk_count(attestation.data.crosslink) * spec.BYTES_PER_CUSTODY_CHUNK)
|
||||
shard_root = get_custody_merkle_root(test_vector)
|
||||
attestation.data.crosslink.data_root = shard_root
|
||||
attestation.custody_bits[0] = 0
|
||||
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||
|
||||
_, _, _ = run_attestation_processing(spec, state, attestation)
|
||||
|
||||
state.slot += spec.SLOTS_PER_EPOCH * (spec.EPOCHS_PER_CUSTODY_PERIOD - 1)
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * (spec.EPOCHS_PER_CUSTODY_PERIOD - 1))
|
||||
|
||||
challenge = get_valid_bit_challenge(spec, state, attestation)
|
||||
data_index = 0
|
||||
|
||||
yield from run_bit_challenge_processing(spec, state, challenge)
|
||||
slashing = get_valid_custody_slashing(spec, state, attestation, shard_transition)
|
||||
|
||||
yield from run_custody_slashing_processing(spec, state, slashing, correct=True)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@spec_state_test
|
||||
def test_off_chain_attestation(spec, state):
|
||||
state.slot = spec.SLOTS_PER_EPOCH
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH)
|
||||
shard = 0
|
||||
offset_slots = spec.get_offset_slots(state, shard)
|
||||
shard_transition = get_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots))
|
||||
data_index = 0
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition, valid_custody_bits=False)
|
||||
|
||||
test_vector = get_custody_test_vector(
|
||||
spec.get_custody_chunk_count(attestation.data.crosslink) * spec.BYTES_PER_CUSTODY_CHUNK)
|
||||
shard_root = get_custody_merkle_root(test_vector)
|
||||
attestation.data.crosslink.data_root = shard_root
|
||||
attestation.custody_bits[0] = 0
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * (spec.EPOCHS_PER_CUSTODY_PERIOD - 1))
|
||||
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
state.slot += spec.SLOTS_PER_EPOCH * spec.EPOCHS_PER_CUSTODY_PERIOD
|
||||
data_index = 0
|
||||
|
||||
challenge = get_valid_bit_challenge(spec, state, attestation)
|
||||
slashing = get_valid_custody_slashing(spec, state, attestation, shard_transition)
|
||||
|
||||
yield from run_bit_challenge_processing(spec, state, challenge)
|
||||
yield from run_custody_slashing_processing(spec, state, slashing, correct=True)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@spec_state_test
|
||||
def test_invalid_custody_bit_challenge(spec, state):
|
||||
state.slot = spec.SLOTS_PER_EPOCH
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
def test_invalid_custody_slashing(spec, state):
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH)
|
||||
shard = 0
|
||||
offset_slots = spec.get_offset_slots(state, shard)
|
||||
shard_transition = get_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots))
|
||||
data_index = 0
|
||||
attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition, valid_custody_bits=False)
|
||||
|
||||
test_vector = get_custody_test_vector(
|
||||
spec.get_custody_chunk_count(attestation.data.crosslink) * spec.BYTES_PER_CUSTODY_CHUNK)
|
||||
shard_root = get_custody_merkle_root(test_vector)
|
||||
attestation.data.crosslink.data_root = shard_root
|
||||
attestation.custody_bits[0] = 0
|
||||
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||
|
||||
_, _, _ = run_attestation_processing(spec, state, attestation)
|
||||
|
||||
state.slot += spec.SLOTS_PER_EPOCH * spec.EPOCHS_PER_CUSTODY_PERIOD
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * (spec.EPOCHS_PER_CUSTODY_PERIOD - 1))
|
||||
|
||||
challenge = get_valid_bit_challenge(spec, state, attestation, invalid_custody_bit=True)
|
||||
data_index = 0
|
||||
|
||||
yield from run_bit_challenge_processing(spec, state, challenge, valid=False)
|
||||
slashing = get_valid_custody_slashing(spec, state, attestation, shard_transition)
|
||||
|
||||
slashing.message.data = ByteList[spec.MAX_SHARD_BLOCK_SIZE]()
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@spec_state_test
|
||||
def test_max_reveal_lateness_1(spec, state):
|
||||
next_epoch(spec, state)
|
||||
apply_empty_block(spec, state)
|
||||
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
|
||||
test_vector = get_custody_test_vector(
|
||||
spec.get_custody_chunk_count(attestation.data.crosslink) * spec.BYTES_PER_CUSTODY_CHUNK)
|
||||
shard_root = get_custody_merkle_root(test_vector)
|
||||
attestation.data.crosslink.data_root = shard_root
|
||||
attestation.custody_bits[0] = 0
|
||||
|
||||
next_epoch(spec, state)
|
||||
apply_empty_block(spec, state)
|
||||
|
||||
_, _, _ = run_attestation_processing(spec, state, attestation)
|
||||
|
||||
challenge = get_valid_bit_challenge(spec, state, attestation)
|
||||
|
||||
responder_index = challenge.responder_index
|
||||
target_epoch = attestation.data.target.epoch
|
||||
|
||||
state.validators[responder_index].max_reveal_lateness = 3
|
||||
|
||||
latest_reveal_epoch = spec.get_randao_epoch_for_custody_period(
|
||||
spec.get_custody_period_for_validator(state, responder_index, target_epoch),
|
||||
responder_index
|
||||
) + 2 * spec.EPOCHS_PER_CUSTODY_PERIOD + state.validators[responder_index].max_reveal_lateness
|
||||
|
||||
while spec.get_current_epoch(state) < latest_reveal_epoch - 2:
|
||||
next_epoch(spec, state)
|
||||
apply_empty_block(spec, state)
|
||||
|
||||
yield from run_bit_challenge_processing(spec, state, challenge)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@spec_state_test
|
||||
def test_max_reveal_lateness_2(spec, state):
|
||||
next_epoch(spec, state)
|
||||
apply_empty_block(spec, state)
|
||||
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
|
||||
test_vector = get_custody_test_vector(
|
||||
spec.get_custody_chunk_count(attestation.data.crosslink) * spec.BYTES_PER_CUSTODY_CHUNK)
|
||||
shard_root = get_custody_merkle_root(test_vector)
|
||||
attestation.data.crosslink.data_root = shard_root
|
||||
attestation.custody_bits[0] = 0
|
||||
|
||||
next_epoch(spec, state)
|
||||
apply_empty_block(spec, state)
|
||||
|
||||
_, _, _ = run_attestation_processing(spec, state, attestation)
|
||||
|
||||
challenge = get_valid_bit_challenge(spec, state, attestation)
|
||||
|
||||
responder_index = challenge.responder_index
|
||||
|
||||
state.validators[responder_index].max_reveal_lateness = 3
|
||||
|
||||
for i in range(spec.get_randao_epoch_for_custody_period(
|
||||
spec.get_custody_period_for_validator(state, responder_index),
|
||||
responder_index
|
||||
) + 2 * spec.EPOCHS_PER_CUSTODY_PERIOD + state.validators[responder_index].max_reveal_lateness - 1):
|
||||
next_epoch(spec, state)
|
||||
apply_empty_block(spec, state)
|
||||
|
||||
yield from run_bit_challenge_processing(spec, state, challenge, False)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@spec_state_test
|
||||
def test_custody_response(spec, state):
|
||||
state.slot = spec.SLOTS_PER_EPOCH
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
|
||||
test_vector = get_custody_test_vector(
|
||||
spec.get_custody_chunk_count(attestation.data.crosslink) * spec.BYTES_PER_CUSTODY_CHUNK)
|
||||
shard_root = get_custody_merkle_root(test_vector)
|
||||
attestation.data.crosslink.data_root = shard_root
|
||||
attestation.custody_bits[0] = 0
|
||||
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
|
||||
_, _, _ = run_attestation_processing(spec, state, attestation)
|
||||
|
||||
state.slot += spec.SLOTS_PER_EPOCH * spec.EPOCHS_PER_CUSTODY_PERIOD
|
||||
|
||||
challenge = get_valid_bit_challenge(spec, state, attestation)
|
||||
|
||||
_, _, _ = run_bit_challenge_processing(spec, state, challenge)
|
||||
|
||||
bit_challenge_index = state.custody_bit_challenge_index - 1
|
||||
|
||||
custody_response = get_valid_custody_bit_response(spec, state, challenge, test_vector, bit_challenge_index)
|
||||
|
||||
yield from run_custody_bit_response_processing(spec, state, custody_response)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@spec_state_test
|
||||
def test_custody_response_multiple_epochs(spec, state):
|
||||
state.slot = spec.SLOTS_PER_EPOCH * 3
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
|
||||
test_vector = get_custody_test_vector(
|
||||
spec.get_custody_chunk_count(attestation.data.crosslink) * spec.BYTES_PER_CUSTODY_CHUNK)
|
||||
shard_root = get_custody_merkle_root(test_vector)
|
||||
attestation.data.crosslink.data_root = shard_root
|
||||
attestation.custody_bits[0] = 0
|
||||
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
|
||||
_, _, _ = run_attestation_processing(spec, state, attestation)
|
||||
|
||||
state.slot += spec.SLOTS_PER_EPOCH * spec.EPOCHS_PER_CUSTODY_PERIOD
|
||||
|
||||
challenge = get_valid_bit_challenge(spec, state, attestation)
|
||||
|
||||
_, _, _ = run_bit_challenge_processing(spec, state, challenge)
|
||||
|
||||
bit_challenge_index = state.custody_bit_challenge_index - 1
|
||||
|
||||
custody_response = get_valid_custody_bit_response(spec, state, challenge, test_vector, bit_challenge_index)
|
||||
|
||||
yield from run_custody_bit_response_processing(spec, state, custody_response)
|
||||
|
||||
|
||||
@with_all_phases_except(['phase0'])
|
||||
@spec_state_test
|
||||
def test_custody_response_many_epochs(spec, state):
|
||||
state.slot = spec.SLOTS_PER_EPOCH * 100
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
|
||||
test_vector = get_custody_test_vector(
|
||||
spec.get_custody_chunk_count(attestation.data.crosslink) * spec.BYTES_PER_CUSTODY_CHUNK)
|
||||
shard_root = get_custody_merkle_root(test_vector)
|
||||
attestation.data.crosslink.data_root = shard_root
|
||||
attestation.custody_bits[0] = 0
|
||||
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
|
||||
_, _, _ = run_attestation_processing(spec, state, attestation)
|
||||
|
||||
state.slot += spec.SLOTS_PER_EPOCH * spec.EPOCHS_PER_CUSTODY_PERIOD
|
||||
|
||||
challenge = get_valid_bit_challenge(spec, state, attestation)
|
||||
|
||||
_, _, _ = run_bit_challenge_processing(spec, state, challenge)
|
||||
|
||||
bit_challenge_index = state.custody_bit_challenge_index - 1
|
||||
|
||||
custody_response = get_valid_custody_bit_response(spec, state, challenge, test_vector, bit_challenge_index)
|
||||
|
||||
yield from run_custody_bit_response_processing(spec, state, custody_response)
|
||||
yield from run_custody_slashing_processing(spec, state, slashing, valid=False)
|
||||
|
|
Loading…
Reference in New Issue