restore network sim finalization

* relax attestation validation when attestation is incoming but make it
more strict when adding to block
* share attestation validation logic between attestation pool and state
transition
* remove a bunch of redundant logging
* fix potential underflow in attestation delay checking
* fix committee used for attestation shard selection when attesting
* fix attestation data construction
This commit is contained in:
Jacek Sieka 2019-08-19 18:41:13 +02:00 committed by zah
parent 225465578c
commit 78f7a4a505
9 changed files with 224 additions and 269 deletions

View File

@ -6,6 +6,9 @@ import
beacon_node_types
proc init*(T: type AttestationPool, blockPool: BlockPool): T =
# TODO blockPool is only used when resolving orphaned attestations - it should
# probably be removed as a dependency of AttestationPool (or some other
# smart refactoring)
T(
slots: initDeque[SlotData](),
blockPool: blockPool,
@ -32,81 +35,39 @@ proc combine*(tgt: var Attestation, src: Attestation, flags: UpdateFlags) =
debug "Ignoring overlapping attestations"
proc validate(
state: BeaconState, attestation: Attestation, flags: UpdateFlags): bool =
# TODO these validations should probably be done elsewhere, and really bad
# attestations should probably cause some sort of feedback to the network
# layer so they don't spread further.. is there a sliding scale here of
# badness?
# TODO half of this stuff is from beaconstate.validateAttestation - merge?
let attestationSlot = get_attestation_data_slot(state, attestation.data)
if attestationSlot <
state.finalized_checkpoint.epoch.compute_start_slot_of_epoch():
debug "Old attestation",
attestationSlot = shortLog(attestationSlot),
attestationEpoch = shortLog(attestationSlot.compute_epoch_of_slot),
stateSlot = shortLog(state.slot),
finalizedEpoch = shortLog(state.finalized_checkpoint.epoch)
state: BeaconState, attestation: Attestation): bool =
# TODO what constitutes a valid attestation when it's about to be added to
# the pool? we're interested in attestations that will become viable
# for inclusion in blocks in the future and on any fork, so we need to
# consider that validations might happen using the state of a different
# fork.
# Some things are always invalid (like out-of-bounds issues etc), but
# others are more subtle - how do we validate the signature for example?
# It might be valid on one fork but not another. One thing that helps
# is that committees are stable per epoch and that it should be OK to
# include an attestation in a block even if the corresponding validator
# was slashed in the same epoch - there's no penalty for doing this and
# the vote counting logic will take care of any ill effects (TODO verify)
let data = attestation.data
if not (data.crosslink.shard < SHARD_COUNT):
notice "Attestation shard too high",
attestation_shard = data.crosslink.shard
return
# TODO what makes sense here? If an attestation is from the future with
# regards to the state, something is wrong - it's a bad attestation, we're
# desperatly behind or someone is sending bogus attestations...
if attestationSlot > state.slot + 64:
debug "Future attestation",
attestationSlot = shortLog(attestationSlot),
attestationEpoch = shortLog(attestationSlot.compute_epoch_of_slot),
stateSlot = shortLog(state.slot),
finalizedEpoch = shortLog(state.finalized_checkpoint.epoch)
# Without this check, we can't get a slot number for the attestation as
# certain helpers will assert
# TODO this could probably be avoided by being smart about the specific state
# used to validate the attestation: most likely if we pick the state of
# the beacon block being voted for and a slot in the target epoch
# of the attestation, we'll be safe!
# TODO the above state selection logic should probably live here in the
# attestation pool
if not (data.target.epoch == get_previous_epoch(state) or
data.target.epoch == get_current_epoch(state)):
notice "Target epoch not current or previous epoch"
return
if not attestation.custody_bits.BitSeq.isZeros:
notice "Invalid custody bitfield for phase 0"
return false
if attestation.aggregation_bits.BitSeq.isZeros:
notice "Empty aggregation bitfield"
return false
## the rest; turns into expensive NOP until then.
if skipValidation notin flags:
let
participants = get_attesting_indices_seq(
state, attestation.data, attestation.aggregation_bits)
## TODO when the custody_bits assertion-to-emptiness disappears do this
## and fix the custody_bit_0_participants check to depend on it.
# custody_bit_1_participants = {nothing, always, because assertion above}
custody_bit_1_participants: seq[ValidatorIndex] = @[]
custody_bit_0_participants = participants
group_public_key = bls_aggregate_pubkeys(
participants.mapIt(state.validators[it].pubkey))
# Verify that aggregate_signature verifies using the group pubkey.
if not bls_verify_multiple(
@[
bls_aggregate_pubkeys(mapIt(custody_bit_0_participants,
state.validators[it].pubkey)),
bls_aggregate_pubkeys(mapIt(custody_bit_1_participants,
state.validators[it].pubkey)),
],
@[
hash_tree_root(AttestationDataAndCustodyBit(
data: attestation.data, custody_bit: false)),
hash_tree_root(AttestationDataAndCustodyBit(
data: attestation.data, custody_bit: true)),
],
attestation.signature,
get_domain(state, DOMAIN_ATTESTATION,
compute_epoch_of_slot(get_attestation_data_slot(state, attestation.data))),
):
notice "Invalid signature", participants
return false
true
proc slotIndex(
@ -173,14 +134,19 @@ proc updateLatestVotes(
proc add*(pool: var AttestationPool,
state: BeaconState,
blck: BlockRef,
attestation: Attestation) =
# TODO there are constraints on the state and block being passed in here
# but what these are is unclear.. needs analyzing from a high-level
# perspective / spec intent
# TODO should update the state correctly in here instead of forcing the caller
# to do it...
doAssert blck.root == attestation.data.beacon_block_root
var cache = get_empty_per_epoch_cache()
# TODO should validate against the state of the block being attested to?
if not validate(state, attestation, {skipValidation}):
debug "attestationPool:add:notValidate",
if not validate(state, attestation):
notice "Invalid attestation",
attestationData = shortLog(attestation.data),
validatorIndex = get_attesting_indices(state, attestation.data, attestation.aggregation_bits, cache),
current_epoch = get_current_epoch(state),
target_epoch = attestation.data.target.epoch,
stateSlot = state.slot
@ -220,15 +186,16 @@ proc add*(pool: var AttestationPool,
if not found:
# Attestations in the pool that are a subset of the new attestation
# can now be removed per same logic as above
debug "Removing subset attestations",
existingParticipants = a.validations.filterIt(
it.aggregation_bits.isSubsetOf(validation.aggregation_bits)
).mapIt(get_attesting_indices_seq(
state, a.data, it.aggregation_bits)),
newParticipants = participants
a.validations.keepItIf(
if it.aggregation_bits.isSubsetOf(validation.aggregation_bits):
debug "Removing subset attestation",
existingParticipants = get_attesting_indices_seq(
state, a.data, it.aggregation_bits),
newParticipants = participants
false
else:
true)
not it.aggregation_bits.isSubsetOf(validation.aggregation_bits))
a.validations.add(validation)
pool.updateLatestVotes(state, attestationSlot, participants, a.blck)
@ -236,7 +203,8 @@ proc add*(pool: var AttestationPool,
info "Attestation resolved",
attestationData = shortLog(attestation.data),
validations = a.validations.len(),
validatorIndex = get_attesting_indices(state, attestation.data, attestation.aggregation_bits, cache),
validatorIndex = get_attesting_indices(
state, attestation.data, attestation.aggregation_bits, cache),
current_epoch = get_current_epoch(state),
target_epoch = attestation.data.target.epoch,
stateSlot = state.slot
@ -246,33 +214,32 @@ proc add*(pool: var AttestationPool,
break
if not found:
if (let blck = pool.blockPool.getOrResolve(
attestation.data.beacon_block_root); blck != nil):
slotData.attestations.add(AttestationEntry(
data: attestation.data,
blck: blck,
validations: @[validation]
))
pool.updateLatestVotes(state, attestationSlot, participants, blck)
slotData.attestations.add(AttestationEntry(
data: attestation.data,
blck: blck,
validations: @[validation]
))
pool.updateLatestVotes(state, attestationSlot, participants, blck)
info "Attestation resolved",
attestationData = shortLog(attestation.data),
validatorIndex = get_attesting_indices(state, attestation.data, attestation.aggregation_bits, cache),
current_epoch = get_current_epoch(state),
target_epoch = attestation.data.target.epoch,
stateSlot = state.slot,
validations = 1
info "Attestation resolved",
attestationData = shortLog(attestation.data),
validatorIndex = get_attesting_indices(
state, attestation.data, attestation.aggregation_bits, cache),
current_epoch = get_current_epoch(state),
target_epoch = attestation.data.target.epoch,
stateSlot = state.slot,
validations = 1
else:
pool.unresolved[attestation.data.beacon_block_root] =
UnresolvedAttestation(
attestation: attestation,
)
proc addUnresolved*(pool: var AttestationPool, attestation: Attestation) =
pool.unresolved[attestation.data.beacon_block_root] =
UnresolvedAttestation(
attestation: attestation,
)
proc getAttestationsForBlock*(
pool: AttestationPool, state: var BeaconState,
pool: AttestationPool, state: BeaconState,
newBlockSlot: Slot): seq[Attestation] =
if newBlockSlot - GENESIS_SLOT < MIN_ATTESTATION_INCLUSION_DELAY:
if newBlockSlot < (GENESIS_SLOT + MIN_ATTESTATION_INCLUSION_DELAY):
debug "Too early for attestations",
newBlockSlot = shortLog(newBlockSlot)
return
@ -313,14 +280,21 @@ proc getAttestationsForBlock*(
signature: a.validations[0].aggregate_signature
)
if not validate(state, attestation):
warn "Attestation no longer validates..."
continue
# TODO what's going on here is that when producing a block, we need to
# include only such attestations that will not cause block validation
# to fail. How this interacts with voting and the acceptance of
# attestations into the pool in general is an open question that needs
# revisiting - for example, when attestations are added, against which
# state should they be validated, if at all?
if not process_attestation(
state, attestation, {skipValidation, nextSlot}, cache):
# TODO we're checking signatures here every time which is very slow - this
# is needed because validate does nothing for now and we don't want
# to include a broken attestation
if not check_attestation(
state, attestation, {nextSlot}, cache):
continue
for v in a.validations[1..^1]:
@ -350,26 +324,28 @@ proc getAttestationsForTargetEpoch*(
for s in begin_slot .. end_slot_minus1:
result.add getAttestationsForBlock(pool, state, s.Slot)
proc resolve*(pool: var AttestationPool, state: BeaconState) =
var done: seq[Eth2Digest]
var resolved: seq[Attestation]
proc resolve*(pool: var AttestationPool, cache: var StateData) =
var
done: seq[Eth2Digest]
resolved: seq[tuple[blck: BlockRef, attestation: Attestation]]
for k, v in pool.unresolved.mpairs():
let attestation_slot = get_attestation_data_slot(state, v.attestation.data)
if v.tries > 8 or attestation_slot < pool.startingSlot:
if (let blck = pool.blockPool.getRef(k); not blck.isNil()):
resolved.add((blck, v.attestation))
done.add(k)
elif v.tries > 8:
done.add(k)
else:
if pool.blockPool.get(k).isSome():
resolved.add(v.attestation)
done.add(k)
else:
inc v.tries
inc v.tries
for k in done:
pool.unresolved.del(k)
for a in resolved:
pool.add(state, a)
pool.blockPool.updateStateData(
cache, BlockSlot(blck: a.blck, slot: a.blck.slot))
pool.add(cache.data.data, a.blck, a.attestation)
proc latestAttestation*(
pool: AttestationPool, pubKey: ValidatorPubKey): BlockRef =

View File

@ -271,22 +271,21 @@ proc getAttachedValidator(
proc updateHead(node: BeaconNode, slot: Slot): BlockRef =
# Use head state for attestation resolution below
# TODO do we need to resolve attestations using all available head states?
node.blockPool.withState(
node.stateCache, BlockSlot(blck: node.blockPool.head.blck, slot: slot)):
# Check pending attestations - maybe we found some blocks for them
node.attestationPool.resolve(state)
# TODO move all of this logic to BlockPool
debug "Preparing for fork choice",
stateRoot = shortLog(root),
connectedPeers = node.network.peersCount,
stateSlot = shortLog(state.slot),
stateEpoch = shortLog(state.slot.computeEpochOfSlot)
# Check pending attestations - maybe we found some blocks for them
node.attestationPool.resolve(node.stateCache)
# TODO move all of this logic to BlockPool
let
justifiedHead = node.blockPool.latestJustifiedBlock()
debug "Preparing for fork choice",
justifiedHeadRoot = shortLog(justifiedHead.root),
justifiedHeadSlot = shortLog(justifiedHead.slot),
justifiedHeadEpoch = shortLog(justifiedHead.slot.compute_epoch_of_slot),
connectedPeers = node.network.peersCount
# TODO slot number is wrong here, it should be the start of the epoch that
# got finalized:
# https://github.com/ethereum/eth2.0-specs/issues/768
@ -295,6 +294,7 @@ proc updateHead(node: BeaconNode, slot: Slot): BlockRef =
BlockSlot(blck: justifiedHead, slot: justifiedHead.slot)):
lmdGhost(node.attestationPool, state, justifiedHead)
info "Fork chosen",
newHeadSlot = shortLog(newHead.slot),
newHeadEpoch = shortLog(newHead.slot.computeEpochOfSlot),
@ -414,37 +414,30 @@ proc onAttestation(node: BeaconNode, attestation: Attestation) =
attestationData = shortLog(attestation.data),
signature = shortLog(attestation.signature)
let
wallSlot = node.beaconClock.now().toSlot()
head = node.blockPool.head
if (let attestedBlock = node.blockPool.getOrResolve(
attestation.data.beacon_block_root); attestedBlock != nil):
let
wallSlot = node.beaconClock.now().toSlot()
head = node.blockPool.head
if not wallSlot.afterGenesis or wallSlot.slot < head.blck.slot:
warn "Received attestation before genesis or head - clock is wrong?",
afterGenesis = wallSlot.afterGenesis,
wallSlot = shortLog(wallSlot.slot),
headSlot = shortLog(head.blck.slot)
return
if not wallSlot.afterGenesis or wallSlot.slot < head.blck.slot:
warn "Received attestation before genesis or head - clock is wrong?",
afterGenesis = wallSlot.afterGenesis,
wallSlot = shortLog(wallSlot.slot),
headSlot = shortLog(head.blck.slot)
return
# TODO seems reasonable to use the latest head state here.. needs thinking
# though - maybe we should use the state from the block pointed to by
# the attestation for some of the check? Consider interop with block
# production!
node.blockPool.withState(node.stateCache,
BlockSlot(blck: head.blck, slot: wallSlot.slot)):
var stateCache = get_empty_per_epoch_cache()
node.attestationPool.add(state, attestation)
# TODO seems reasonable to use the latest head state here.. needs thinking
# though - maybe we should use the state from the block pointed to by
# the attestation for some of the check? Consider interop with block
# production!
let
bs = BlockSlot(blck: head.blck, slot: wallSlot.slot)
debug "Attestation received 2",
start_attestation_data_slot =
get_attestation_data_slot(state, attestation.data),
indexed_attesters =
get_indexed_attestation(state, attestation, stateCache),
target_epoch =
attestation.data.target.epoch,
cur_epoch = get_current_epoch(state),
cur_slot = state.slot
#doAssert get_current_epoch(state) < attestation.data.target.epoch or state.slot <= get_attestation_data_slot(state, attestation.data)
node.blockPool.withState(node.stateCache, bs):
node.attestationPool.add(state, attestedBlock, attestation)
else:
node.attestationPool.addUnresolved(attestation)
proc onBeaconBlock(node: BeaconNode, blck: BeaconBlock) =
# We received a block but don't know much about it yet - in particular, we
@ -494,7 +487,6 @@ proc handleAttestations(node: BeaconNode, head: BlockRef, slot: Slot) =
attestationHeadRoot = shortLog(attestationHead.blck.root),
attestationSlot = shortLog(slot)
# Collect data to send before node.stateCache grows stale
var attestations: seq[tuple[
data: AttestationData, committeeLen, indexInCommittee: int,
@ -503,30 +495,30 @@ proc handleAttestations(node: BeaconNode, head: BlockRef, slot: Slot) =
# We need to run attestations exactly for the slot that we're attesting to.
# In case blocks went missing, this means advancing past the latest block
# using empty slots as fillers.
# https://github.com/ethereum/eth2.0-specs/blob/v0.8.2/specs/validator/0_beacon-chain-validator.md#validator-assignments
# TODO we could cache the validator assignment since it's valid for the entire
# epoch since it doesn't change, but that has to be weighed against
# the complexity of handling forks correctly - instead, we use an adapted
# version here that calculates the committee for a single slot only
node.blockPool.withState(node.stateCache, attestationHead):
var cache = get_empty_per_epoch_cache()
let epoch = compute_epoch_of_slot(slot)
for committee_index in 0'u64 ..< get_committee_count(state, epoch):
## TODO verify that this is the correct mapping; it's consistent with
## other code
let
epoch = compute_epoch_of_slot(slot)
committees_per_slot = get_committee_count(state, epoch) div SLOTS_PER_EPOCH
start_slot = compute_start_slot_of_epoch(epoch)
offset = committees_per_slot * (slot mod SLOTS_PER_EPOCH)
slot_start_shard = (get_start_shard(state, epoch) + offset) mod SHARD_COUNT
for i in 0'u64..<committees_per_slot:
let
shard = committee_index mod SHARD_COUNT
shard2 = (committee_index + get_start_shard(state, epoch)) mod SHARD_COUNT
committee = get_crosslink_committee(state, epoch, shard2, cache)
shard = Shard((slot_start_shard + i) mod SHARD_COUNT)
committee = get_crosslink_committee(state, epoch, shard, cache)
for i, validatorIdx in committee:
let validator = node.getAttachedValidator(state, validatorIdx)
if validator != nil:
let ad = makeAttestationData(state, shard2, blck.root)
attestations.add (
ad,
committee.len, i, validator)
debug "handleAttestations: adding attestation to list for broadcast",
data=ad,
epoch=epoch,
committeeIdx = i,
validatorIdx = validatorIdx.int,
shard=shard2,
committee = committee
let ad = makeAttestationData(state, shard, blck.root)
attestations.add((ad, committee.len, i, validator))
for a in attestations:
traceAsyncErrors sendAttestation(
@ -543,35 +535,10 @@ proc handleProposal(node: BeaconNode, head: BlockRef, slot: Slot):
# revisit this - we should be able to advance behind
var cache = get_empty_per_epoch_cache()
node.blockPool.withState(node.stateCache, BlockSlot(blck: head, slot: slot)):
# justification won't happen in odd case anyway
let prev_epoch = get_previous_epoch(state)
let prev_epoch_attestations = node.attestationPool.getAttestationsForTargetEpoch(state, prev_epoch)
debug "handleProposal: getAttestationsForTargetEpoch attesting indices for prev_epoch",
attesting_indices = mapIt(prev_epoch_attestations, get_attesting_indices(state, it.data, it.aggregation_bits, cache))
let
proposerIdx = get_beacon_proposer_index(state, cache)
validator = node.getAttachedValidator(state, proposerIdx)
# Ugly hack.
# TODO handle MAX_ATTESTATIONS & merging pointless dupes for this purpose?
blockBody2 = BeaconBlockBody(
attestations:
#node.attestationPool.getAttestationsForBlock(state, slot - min(MIN_ATTESTATION_INCLUSION_DELAY.uint64, slot.uint64)))
prev_epoch_attestations)
newBlock2 = BeaconBlock(
slot: slot,
parent_root: head.root,
body: blockBody2
)
if newBlock2.slot > 0 and not processAttestations(state, newBlock2, {skipValidation}, cache):
debug "when calling processAttestations from handleAttestations, failed"
else:
debug "when calling processAttestations from handleAttestations, succeeded"
if validator != nil:
return await proposeBlock(node, validator, head, slot)

View File

@ -467,8 +467,9 @@ func get_indexed_attestation*(state: BeaconState, attestation: Attestation,
)
# https://github.com/ethereum/eth2.0-specs/blob/v0.8.1/specs/core/0_beacon-chain.md#attestations
proc process_attestation*(
state: var BeaconState, attestation: Attestation, flags: UpdateFlags,
proc check_attestation*(
state: BeaconState, attestation: Attestation, flags: UpdateFlags,
stateCache: var StateCache): bool =
## Check that an attestation follows the rules of being included in the state
## at the current slot. When acting as a proposer, the same rules need to
@ -480,7 +481,7 @@ proc process_attestation*(
let data = attestation.data
debug "process_attestation: beginning",
trace "process_attestation: beginning",
attestation=attestation
if not (data.crosslink.shard < SHARD_COUNT):
@ -507,13 +508,6 @@ proc process_attestation*(
state_slot = shortLog(stateSlot))
return
let pending_attestation = PendingAttestation(
data: data,
aggregation_bits: attestation.aggregation_bits,
inclusion_delay: state.slot - attestation_slot,
proposer_index: get_beacon_proposer_index(state, stateCache),
)
# Check FFG data, crosslink data, and signature
let ffg_check_data = (data.source.epoch, data.source.root, data.target.epoch)
@ -528,11 +522,6 @@ proc process_attestation*(
hash_tree_root(state.current_crosslinks[data.crosslink.shard])):
warn("Crosslink shard's current crosslinks not matching crosslink parent root")
return
debug "process_attestation: current_epoch_attestations.add",
pending_attestation = pending_attestation,
validator_index = get_attesting_indices(state, attestation.data, attestation.aggregation_bits, cache)
state.current_epoch_attestations.add(pending_attestation)
else:
if not (ffg_check_data == (state.previous_justified_checkpoint.epoch,
state.previous_justified_checkpoint.root, get_previous_epoch(state))):
@ -544,11 +533,6 @@ proc process_attestation*(
warn("Crosslink shard's previous crosslinks not matching crosslink parent root")
return
debug "process_attestation: previous_epoch_attestations.add",
pending_attestation = pending_attestation,
validator_index = get_attesting_indices(state, attestation.data, attestation.aggregation_bits, cache)
state.previous_epoch_attestations.add(pending_attestation)
let parent_crosslink = if data.target.epoch == get_current_epoch(state):
state.current_crosslinks[data.crosslink.shard]
else:
@ -583,43 +567,71 @@ proc process_attestation*(
true
proc process_attestation*(
state: var BeaconState, attestation: Attestation, flags: UpdateFlags,
stateCache: var StateCache): bool =
# In the spec, attestation validation is mixed with state mutation, so here
# we've split it into two functions so that the validation logic can be
# reused when looking for suitable blocks to include in attestations.
# TODO don't log warnings when looking for attestations (return
# Result[void, cstring] instead of logging in check_attestation?)
if check_attestation(state, attestation, flags, stateCache):
let
attestation_slot = get_attestation_data_slot(state, attestation.data)
pending_attestation = PendingAttestation(
data: attestation.data,
aggregation_bits: attestation.aggregation_bits,
inclusion_delay: state.slot - attestation_slot,
proposer_index: get_beacon_proposer_index(state, stateCache),
)
if attestation.data.target.epoch == get_current_epoch(state):
trace "process_attestation: current_epoch_attestations.add",
pending_attestation = pending_attestation,
indices = get_attesting_indices(
state, attestation.data, attestation.aggregation_bits, stateCache).len
state.current_epoch_attestations.add(pending_attestation)
else:
trace "process_attestation: previous_epoch_attestations.add",
pending_attestation = pending_attestation,
indices = get_attesting_indices(
state, attestation.data, attestation.aggregation_bits, stateCache).len
state.previous_epoch_attestations.add(pending_attestation)
true
else:
false
proc makeAttestationData*(
state: BeaconState, shard_offset: uint64,
state: BeaconState, shard: uint64,
beacon_block_root: Eth2Digest): AttestationData =
## Fine points:
## Head must be the head state during the slot that validator is
## part of committee - notably, it can't be a newer or older state (!)
## Create an attestation / vote for the block `beacon_block_root` using the
## data in `state` to fill in the rest of the fields.
## `state` is the state corresponding to the `beacon_block_root` advanced to
## the slot we're attesting to.
## https://github.com/ethereum/eth2.0-specs/blob/v0.8.2/specs/validator/0_beacon-chain-validator.md#construct-attestation
let
epoch_start_slot = compute_start_slot_of_epoch(compute_epoch_of_slot(state.slot))
#shard = (shard_offset + get_start_shard(state,
# compute_epoch_of_slot(state.slot))) mod SHARD_COUNT
shard = shard_offset
# TODO incorrect epoch for wraparound cases
target_epoch = compute_epoch_of_slot(state.slot)
# TODO wrong target_root when epoch_start_slot == state.slot
target_root =
if epoch_start_slot == state.slot: beacon_block_root
else: get_block_root_at_slot(state, epoch_start_slot)
debug "makeAttestationData",
target_epoch=target_epoch,
target_root=target_root,
state_slot = state.slot,
epoch_start_slot = epoch_start_slot,
beacon_block_root = beacon_block_root
current_epoch = get_current_epoch(state)
start_slot = compute_start_slot_of_epoch(current_epoch)
epoch_boundary_block_root =
if start_slot == state.slot: beacon_block_root
else: get_block_root_at_slot(state, start_slot)
parent_crosslink_end_epoch = state.current_crosslinks[shard].end_epoch
AttestationData(
beacon_block_root: beacon_block_root,
source: state.current_justified_checkpoint,
target: Checkpoint(
root: target_root,
epoch: target_epoch
epoch: current_epoch,
root: epoch_boundary_block_root
),
crosslink: Crosslink(
shard: shard,
parent_root: hash_tree_root(state.current_crosslinks[shard]),
start_epoch: state.current_crosslinks[shard].end_epoch,
end_epoch: target_epoch,
start_epoch: parent_crosslink_end_epoch,
end_epoch: min(
current_epoch, parent_crosslink_end_epoch + MAX_EPOCHS_PER_CROSSLINK),
)
)

View File

@ -265,7 +265,7 @@ proc processAttestations*(
notice "Attestation: too many!", attestations = blck.body.attestations.len
return false
debug "in processAttestations, not processed attestations",
trace "in processAttestations, not processed attestations",
attestations_len = blck.body.attestations.len()
if not blck.body.attestations.allIt(process_attestation(state, it, flags, stateCache)):
@ -275,7 +275,7 @@ proc processAttestations*(
# Apply the attestations
var committee_count_cache = initTable[Epoch, uint64]()
debug "in processAttestations, has processed attestations",
trace "in processAttestations, has processed attestations",
attestations_len = blck.body.attestations.len()
var cache = get_empty_per_epoch_cache()
@ -305,7 +305,7 @@ proc processAttestations*(
else:
state.previous_epoch_attestations.add(pending_attestation)
debug "processAttestations",
trace "processAttestations",
target_epoch=attestation.data.target.epoch,
current_epoch= get_current_epoch(state),
current_epoch_attestations_len=len(get_attesting_indices(state, state.current_epoch_attestations, cache)),

View File

@ -517,20 +517,20 @@ proc process_final_updates(state: var BeaconState) =
SHARD_COUNT
# Rotate current/previous epoch attestations
debug "Rotating epoch attestations",
trace "Rotating epoch attestations",
current_epoch = get_current_epoch(state)
state.previous_epoch_attestations = state.current_epoch_attestations
state.current_epoch_attestations = @[]
debug "Rotated epoch attestations",
trace "Rotated epoch attestations",
current_epoch = get_current_epoch(state)
# https://github.com/ethereum/eth2.0-specs/blob/v0.8.2/specs/core/0_beacon-chain.md#per-epoch-processing
proc process_epoch*(state: var BeaconState) =
# @proc are placeholders
debug "process_epoch",
trace "process_epoch",
current_epoch = get_current_epoch(state)
var per_epoch_cache = get_empty_per_epoch_cache()
@ -538,7 +538,7 @@ proc process_epoch*(state: var BeaconState) =
# https://github.com/ethereum/eth2.0-specs/blob/v0.8.2/specs/core/0_beacon-chain.md#justification-and-finalization
process_justification_and_finalization(state, per_epoch_cache)
debug "ran process_justification_and_finalization",
trace "ran process_justification_and_finalization",
current_epoch = get_current_epoch(state)
# https://github.com/ethereum/eth2.0-specs/blob/v0.8.2/specs/core/0_beacon-chain.md#crosslinks

View File

@ -64,12 +64,12 @@ proc process_slots*(state: var BeaconState, slot: Slot) =
if (state.slot + 1) mod SLOTS_PER_EPOCH == 0:
# Note: Genesis epoch = 0, no need to test if before Genesis
process_epoch(state)
debug "process_slots: Incrementing slot",
trace "process_slots: Incrementing slot",
state_slot_now = state.slot,
state_slot_next = state.slot + 1,
cur_epoch = get_current_epoch(state)
state.slot += 1
debug "process_slots: Incremented slot",
trace "process_slots: Incremented slot",
cur_epoch = get_current_epoch(state)
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.3/specs/core/0_beacon-chain.md#state-root-verification
@ -178,7 +178,7 @@ proc process_slots*(state: var HashedBeaconState, slot: Slot) =
if (state.data.slot + 1) mod SLOTS_PER_EPOCH == 0:
# Note: Genesis epoch = 0, no need to test if before Genesis
process_epoch(state.data)
debug "process_slots_HashedBeaconState_: Incrementing slot",
trace "process_slots_HashedBeaconState_: Incrementing slot",
state_slot_now = state.data.slot,
state_slot_next = state.data.slot + 1,
cur_epoch = get_current_epoch(state.data)

View File

@ -21,7 +21,7 @@ mkdir -p "${BUILD_OUTPUTS_DIR}"
DEFS="-d:chronicles_log_level=DEBUG "
DEFS+="-d:SHARD_COUNT=${SHARD_COUNT:-16} " # Spec default: 1024
DEFS+="-d:SLOTS_PER_EPOCH=${SLOTS_PER_EPOCH:-16} " # Spec default: 64
DEFS+="-d:SECONDS_PER_SLOT=${SECONDS_PER_SLOT:-18} " # Spec default: 6
DEFS+="-d:SECONDS_PER_SLOT=${SECONDS_PER_SLOT:-6} " # Spec default: 6
LAST_VALIDATOR_NUM=$(( NUM_VALIDATORS - 1 ))
LAST_VALIDATOR="$VALIDATORS_DIR/v$(printf '%07d' $LAST_VALIDATOR_NUM).deposit.json"

View File

@ -15,7 +15,7 @@ cd - &>/dev/null
: ${BUILD_OUTPUTS_DIR:="$GIT_ROOT/build"}
NUM_VALIDATORS=${VALIDATORS:-1000}
NUM_NODES=${NODES:-2}
NUM_NODES=${NODES:-4}
NUM_MISSING_NODES=${MISSING_NODES:-0}
SIMULATION_DIR="${SIM_ROOT}/data"

View File

@ -44,7 +44,7 @@ suite "Attestation pool processing" & preset():
attestation = makeAttestation(
state.data.data, state.blck.root, crosslink_committee[0])
pool.add(state.data.data, attestation)
pool.add(state.data.data, state.blck, attestation)
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot) # minus 1?
@ -73,8 +73,8 @@ suite "Attestation pool processing" & preset():
state.data.data, state.blck.root, cc1[0])
# test reverse order
pool.add(state.data.data, attestation1)
pool.add(state.data.data, attestation0)
pool.add(state.data.data, state.blck, attestation1)
pool.add(state.data.data, state.blck, attestation0)
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot) # minus 1?
@ -96,8 +96,8 @@ suite "Attestation pool processing" & preset():
attestation1 = makeAttestation(
state.data.data, state.blck.root, cc0[1])
pool.add(state.data.data, attestation0)
pool.add(state.data.data, attestation1)
pool.add(state.data.data, state.blck, attestation0)
pool.add(state.data.data, state.blck, attestation1)
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot) # minus 1?
@ -122,8 +122,8 @@ suite "Attestation pool processing" & preset():
attestation0.combine(attestation1, {skipValidation})
pool.add(state.data.data, attestation0)
pool.add(state.data.data, attestation1)
pool.add(state.data.data, state.blck, attestation0)
pool.add(state.data.data, state.blck, attestation1)
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot) # minus 1?
@ -147,8 +147,8 @@ suite "Attestation pool processing" & preset():
attestation0.combine(attestation1, {skipValidation})
pool.add(state.data.data, attestation1)
pool.add(state.data.data, attestation0)
pool.add(state.data.data, state.blck, attestation1)
pool.add(state.data.data, state.blck, attestation0)
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot) # minus 1?