def update_proposer(self, current_state): # This is a fairly expensive operation, so we try not to call it when we don't have to. # Update proposer duties for the current epoch. # We need to check for each slot of the epoch whether the validator is a proposer or not. current_epoch = specs.get_current_epoch(current_state) start_slot = specs.compute_start_slot_at_epoch(current_epoch) start_state = current_state.copy() if start_slot == current_state.slot else \ self.store.block_states[specs.get_block_root(current_state, current_epoch)].copy() current_proposer_duties = [] for slot in range(start_slot, start_slot + specs.SLOTS_PER_EPOCH): if slot < start_state.slot: current_proposer_duties += [False] continue if start_state.slot < slot: specs.process_slots(start_state, slot) current_proposer_duties += [ specs.get_beacon_proposer_index(start_state) == self.validator_index ] self.data.current_proposer_duties = current_proposer_duties
def disseminate_blocks(params, step, sL, s, _input): start = time.time() network = s["network"] for info_set_index, blocks in enumerate(_input["blocks"]): state = network.sets[info_set_index].beacon_state for block in blocks: if block is None: continue specs.process_block(state, block.message) # process_slots is the bottleneck in terms of speed specs.process_slots(state, state.slot + 1) network.attestations = [ item for item_index, item in enumerate(network.attestations) if item_index not in _input["attestation_indices"] ] if log: print("removing", len(_input["attestation_indices"]), "from network items, there are now", len(network.attestations), "items") if log: print("disseminate_blocks time = ", time.time() - start) return ('network', network)
def process_to_slot(self, current_state_root, slot): # Our cached `process_slots` operation # If we want to fast-forward a state root to some slot, we check if we have already recorded the # resulting state. if (current_state_root, slot) in BRValidator.state_store: return BRValidator.state_store[(current_state_root, slot)].copy() # If we haven't, we need to process it. else: current_state = self.store.block_states[current_state_root].copy() if current_state.slot < slot: specs.process_slots(current_state, slot) BRValidator.state_store[(current_state_root, slot)] = current_state return current_state.copy()
def honest_attest(validator, known_items): # Unpacking validator_index = validator.validator_index store = validator.store committee_slot = validator.data.current_attest_slot committee_index = validator.data.current_committee_index committee = validator.data.current_committee # What am I attesting for? block_root = validator.get_head() head_state = store.block_states[block_root].copy() if head_state.slot < committee_slot: specs.process_slots(head_state, committee_slot) start_slot = specs.compute_start_slot_at_epoch( specs.get_current_epoch(head_state)) epoch_boundary_block_root = block_root if start_slot == head_state.slot else specs.get_block_root_at_slot( head_state, start_slot) tgt_checkpoint = specs.Checkpoint( epoch=specs.get_current_epoch(head_state), root=epoch_boundary_block_root) att_data = specs.AttestationData( index=committee_index, slot=committee_slot, beacon_block_root=block_root, source=head_state.current_justified_checkpoint, target=tgt_checkpoint) # Set aggregation bits to myself only committee_size = len(committee) index_in_committee = committee.index(validator_index) aggregation_bits = Bitlist[specs.MAX_VALIDATORS_PER_COMMITTEE]( *([0] * committee_size)) aggregation_bits[ index_in_committee] = True # set the aggregation bit of the validator to True attestation = specs.Attestation(aggregation_bits=aggregation_bits, data=att_data) # print(validator.validator_index, "attests for slot", committee_slot) return attestation
def transition_state(params, step, sL, s, _input): # Transition from w-[s] to w-[s+1] # `state` is w-[s] state = s['beacon_state'] # We get the block from the policy `propose_block`. new_block = _input['block'] # `state_transition` calls `process_slots` before `process_block`. # Effectively `process_slots` does not do anything here: it would move us from # w+[s-1] to w-[s]. `process_block` takes us from w-[s] to w+[s]. post_state = state_transition(state=state, signed_block=new_block, validate_result=False) # We call `process_slots` to go from w+[s] to w-[s+1] process_slots(post_state, post_state.slot + 1) print("now at state w-[", post_state.slot, "]") return ('beacon_state', post_state)
def __init__(self, state, validator_index): # Validator constructor # We preload a bunch of things, to be updated later on as needed # The validator is initialised from some base state, and given a `validator_index` self.validator_index = validator_index self.store = specs.get_forkchoice_store(state) self.history = [] self.data = ValidatorData() self.data.time_ms = self.store.time * 1000 self.data.recorded_attestations = [] self.data.slot = specs.get_current_slot(self.store) self.data.current_epoch = specs.compute_epoch_at_slot(self.data.slot) self.data.head_root = self.get_head() current_state = state.copy() if current_state.slot < self.data.slot: specs.process_slots(current_state, self.data.slot) self.update_attester(current_state, self.data.current_epoch) self.update_proposer(current_state) self.update_data()