eth2.0-specs/test_libs/pyspec/eth2spec/test/helpers/attestations.py

148 lines
5.2 KiB
Python
Raw Normal View History

2019-05-15 16:36:32 +00:00
from typing import List
2019-05-15 17:31:02 +00:00
from eth2spec.test.helpers.block import build_empty_block_for_next_slot, sign_block
2019-05-15 16:36:32 +00:00
from eth2spec.test.helpers.keys import privkeys
from eth2spec.utils.bls import bls_sign, bls_aggregate_signatures
2019-05-31 23:51:09 +00:00
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
from eth2spec.utils.ssz.ssz_typing import Bitlist
2019-05-15 16:36:32 +00:00
2019-05-30 20:57:18 +00:00
def build_attestation_data(spec, state, slot, shard):
2019-05-15 16:36:32 +00:00
assert state.slot >= slot
if slot == state.slot:
2019-05-30 20:57:18 +00:00
block_root = build_empty_block_for_next_slot(spec, state).parent_root
2019-05-15 16:36:32 +00:00
else:
2019-05-30 20:57:18 +00:00
block_root = spec.get_block_root_at_slot(state, slot)
2019-05-15 16:36:32 +00:00
2019-05-30 20:57:18 +00:00
current_epoch_start_slot = spec.get_epoch_start_slot(spec.get_current_epoch(state))
2019-05-15 16:36:32 +00:00
if slot < current_epoch_start_slot:
2019-05-30 20:57:18 +00:00
epoch_boundary_root = spec.get_block_root(state, spec.get_previous_epoch(state))
2019-05-15 16:36:32 +00:00
elif slot == current_epoch_start_slot:
epoch_boundary_root = block_root
else:
2019-05-30 20:57:18 +00:00
epoch_boundary_root = spec.get_block_root(state, spec.get_current_epoch(state))
2019-05-15 16:36:32 +00:00
if slot < current_epoch_start_slot:
2019-06-22 18:00:26 +00:00
source_epoch = state.previous_justified_checkpoint.epoch
source_root = state.previous_justified_checkpoint.root
2019-05-15 16:36:32 +00:00
else:
2019-06-22 18:00:26 +00:00
source_epoch = state.current_justified_checkpoint.epoch
source_root = state.current_justified_checkpoint.root
2019-05-15 16:36:32 +00:00
2019-05-30 20:57:18 +00:00
if spec.slot_to_epoch(slot) == spec.get_current_epoch(state):
2019-05-27 17:09:52 +00:00
parent_crosslink = state.current_crosslinks[shard]
else:
parent_crosslink = state.previous_crosslinks[shard]
2019-05-30 20:57:18 +00:00
return spec.AttestationData(
2019-05-15 16:36:32 +00:00
beacon_block_root=block_root,
2019-06-22 20:49:53 +00:00
source=spec.Checkpoint(epoch=source_epoch, root=source_root),
target=spec.Checkpoint(epoch=spec.slot_to_epoch(slot), root=epoch_boundary_root),
2019-05-30 20:57:18 +00:00
crosslink=spec.Crosslink(
2019-05-27 17:09:52 +00:00
shard=shard,
start_epoch=parent_crosslink.end_epoch,
2019-05-30 20:57:18 +00:00
end_epoch=min(spec.slot_to_epoch(slot), parent_crosslink.end_epoch + spec.MAX_EPOCHS_PER_CROSSLINK),
2019-05-27 17:09:52 +00:00
data_root=spec.ZERO_HASH,
parent_root=hash_tree_root(parent_crosslink),
),
2019-05-15 16:36:32 +00:00
)
2019-05-30 20:57:18 +00:00
def get_valid_attestation(spec, state, slot=None, signed=False):
2019-05-15 16:36:32 +00:00
if slot is None:
slot = state.slot
2019-05-30 20:57:18 +00:00
epoch = spec.slot_to_epoch(slot)
epoch_start_shard = spec.get_epoch_start_shard(state, epoch)
committees_per_slot = spec.get_epoch_committee_count(state, epoch) // spec.SLOTS_PER_EPOCH
shard = (epoch_start_shard + committees_per_slot * (slot % spec.SLOTS_PER_EPOCH)) % spec.SHARD_COUNT
2019-05-15 16:36:32 +00:00
2019-05-30 20:57:18 +00:00
attestation_data = build_attestation_data(spec, state, slot, shard)
2019-05-15 16:36:32 +00:00
2019-05-30 20:57:18 +00:00
crosslink_committee = spec.get_crosslink_committee(
2019-05-27 17:09:52 +00:00
state,
2019-06-22 20:49:53 +00:00
attestation_data.target.epoch,
2019-06-22 18:00:26 +00:00
attestation_data.crosslink.shard,
2019-05-27 17:09:52 +00:00
)
2019-05-15 16:36:32 +00:00
committee_size = len(crosslink_committee)
2019-06-28 11:23:22 +00:00
aggregation_bits = Bitlist[spec.MAX_INDICES_PER_ATTESTATION](*([0] * committee_size))
custody_bits = Bitlist[spec.MAX_INDICES_PER_ATTESTATION](*([0] * committee_size))
2019-05-30 20:57:18 +00:00
attestation = spec.Attestation(
2019-06-28 11:23:22 +00:00
aggregation_bits=aggregation_bits,
2019-05-15 16:36:32 +00:00
data=attestation_data,
2019-06-28 11:23:22 +00:00
custody_bits=custody_bits,
2019-05-15 16:36:32 +00:00
)
2019-05-30 20:57:18 +00:00
fill_aggregate_attestation(spec, state, attestation)
2019-05-15 17:47:50 +00:00
if signed:
2019-05-30 20:57:18 +00:00
sign_attestation(spec, state, attestation)
2019-05-15 16:36:32 +00:00
return attestation
2019-05-30 20:57:18 +00:00
def sign_aggregate_attestation(spec, state, attestation_data, participants: List[int]):
2019-05-15 16:36:32 +00:00
signatures = []
for validator_index in participants:
privkey = privkeys[validator_index]
signatures.append(
get_attestation_signature(
2019-05-31 08:41:39 +00:00
spec,
2019-05-15 16:36:32 +00:00
state,
2019-05-30 20:57:18 +00:00
attestation_data,
2019-05-15 16:36:32 +00:00
privkey
)
)
return bls_aggregate_signatures(signatures)
2019-05-30 20:57:18 +00:00
def sign_indexed_attestation(spec, state, indexed_attestation):
2019-05-15 16:36:32 +00:00
participants = indexed_attestation.custody_bit_0_indices + indexed_attestation.custody_bit_1_indices
2019-05-30 20:57:18 +00:00
indexed_attestation.signature = sign_aggregate_attestation(spec, state, indexed_attestation.data, participants)
2019-05-15 16:36:32 +00:00
2019-05-30 20:57:18 +00:00
def sign_attestation(spec, state, attestation):
participants = spec.get_attesting_indices(
2019-05-15 16:36:32 +00:00
state,
attestation.data,
2019-06-28 11:23:22 +00:00
attestation.aggregation_bits,
2019-05-15 16:36:32 +00:00
)
2019-05-30 20:57:18 +00:00
attestation.signature = sign_aggregate_attestation(spec, state, attestation.data, participants)
2019-05-15 16:36:32 +00:00
2019-05-30 20:57:18 +00:00
def get_attestation_signature(spec, state, attestation_data, privkey, custody_bit=0b0):
message_hash = spec.AttestationDataAndCustodyBit(
2019-05-15 16:36:32 +00:00
data=attestation_data,
custody_bit=custody_bit,
).hash_tree_root()
return bls_sign(
message_hash=message_hash,
privkey=privkey,
2019-05-30 20:57:18 +00:00
domain=spec.get_domain(
2019-05-15 16:36:32 +00:00
state=state,
domain_type=spec.DOMAIN_ATTESTATION,
2019-06-22 20:49:53 +00:00
message_epoch=attestation_data.target.epoch,
2019-05-15 16:36:32 +00:00
)
)
2019-05-30 20:57:18 +00:00
def fill_aggregate_attestation(spec, state, attestation):
crosslink_committee = spec.get_crosslink_committee(
2019-05-27 17:09:52 +00:00
state,
2019-06-22 20:49:53 +00:00
attestation.data.target.epoch,
2019-05-27 17:09:52 +00:00
attestation.data.crosslink.shard,
)
2019-05-15 16:36:32 +00:00
for i in range(len(crosslink_committee)):
2019-06-28 11:23:22 +00:00
attestation.aggregation_bits[i] = True
2019-05-15 16:36:32 +00:00
2019-05-30 20:57:18 +00:00
def add_attestation_to_state(spec, state, attestation, slot):
block = build_empty_block_for_next_slot(spec, state)
2019-05-15 16:36:32 +00:00
block.slot = slot
block.body.attestations.append(attestation)
2019-05-30 20:57:18 +00:00
spec.process_slots(state, block.slot)
sign_block(spec, state, block)
spec.state_transition(state, block)