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:
parent
225465578c
commit
78f7a4a505
|
@ -6,6 +6,9 @@ import
|
||||||
beacon_node_types
|
beacon_node_types
|
||||||
|
|
||||||
proc init*(T: type AttestationPool, blockPool: BlockPool): T =
|
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(
|
T(
|
||||||
slots: initDeque[SlotData](),
|
slots: initDeque[SlotData](),
|
||||||
blockPool: blockPool,
|
blockPool: blockPool,
|
||||||
|
@ -32,81 +35,39 @@ proc combine*(tgt: var Attestation, src: Attestation, flags: UpdateFlags) =
|
||||||
debug "Ignoring overlapping attestations"
|
debug "Ignoring overlapping attestations"
|
||||||
|
|
||||||
proc validate(
|
proc validate(
|
||||||
state: BeaconState, attestation: Attestation, flags: UpdateFlags): bool =
|
state: BeaconState, attestation: Attestation): bool =
|
||||||
# TODO these validations should probably be done elsewhere, and really bad
|
# TODO what constitutes a valid attestation when it's about to be added to
|
||||||
# attestations should probably cause some sort of feedback to the network
|
# the pool? we're interested in attestations that will become viable
|
||||||
# layer so they don't spread further.. is there a sliding scale here of
|
# for inclusion in blocks in the future and on any fork, so we need to
|
||||||
# badness?
|
# consider that validations might happen using the state of a different
|
||||||
|
# fork.
|
||||||
# TODO half of this stuff is from beaconstate.validateAttestation - merge?
|
# Some things are always invalid (like out-of-bounds issues etc), but
|
||||||
|
# others are more subtle - how do we validate the signature for example?
|
||||||
let attestationSlot = get_attestation_data_slot(state, attestation.data)
|
# 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
|
||||||
if attestationSlot <
|
# include an attestation in a block even if the corresponding validator
|
||||||
state.finalized_checkpoint.epoch.compute_start_slot_of_epoch():
|
# was slashed in the same epoch - there's no penalty for doing this and
|
||||||
debug "Old attestation",
|
# the vote counting logic will take care of any ill effects (TODO verify)
|
||||||
attestationSlot = shortLog(attestationSlot),
|
let data = attestation.data
|
||||||
attestationEpoch = shortLog(attestationSlot.compute_epoch_of_slot),
|
if not (data.crosslink.shard < SHARD_COUNT):
|
||||||
stateSlot = shortLog(state.slot),
|
notice "Attestation shard too high",
|
||||||
finalizedEpoch = shortLog(state.finalized_checkpoint.epoch)
|
attestation_shard = data.crosslink.shard
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# TODO what makes sense here? If an attestation is from the future with
|
# Without this check, we can't get a slot number for the attestation as
|
||||||
# regards to the state, something is wrong - it's a bad attestation, we're
|
# certain helpers will assert
|
||||||
# desperatly behind or someone is sending bogus attestations...
|
# TODO this could probably be avoided by being smart about the specific state
|
||||||
if attestationSlot > state.slot + 64:
|
# used to validate the attestation: most likely if we pick the state of
|
||||||
debug "Future attestation",
|
# the beacon block being voted for and a slot in the target epoch
|
||||||
attestationSlot = shortLog(attestationSlot),
|
# of the attestation, we'll be safe!
|
||||||
attestationEpoch = shortLog(attestationSlot.compute_epoch_of_slot),
|
# TODO the above state selection logic should probably live here in the
|
||||||
stateSlot = shortLog(state.slot),
|
# attestation pool
|
||||||
finalizedEpoch = shortLog(state.finalized_checkpoint.epoch)
|
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
|
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
|
true
|
||||||
|
|
||||||
proc slotIndex(
|
proc slotIndex(
|
||||||
|
@ -173,14 +134,19 @@ proc updateLatestVotes(
|
||||||
|
|
||||||
proc add*(pool: var AttestationPool,
|
proc add*(pool: var AttestationPool,
|
||||||
state: BeaconState,
|
state: BeaconState,
|
||||||
|
blck: BlockRef,
|
||||||
attestation: Attestation) =
|
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()
|
var cache = get_empty_per_epoch_cache()
|
||||||
|
|
||||||
# TODO should validate against the state of the block being attested to?
|
if not validate(state, attestation):
|
||||||
if not validate(state, attestation, {skipValidation}):
|
notice "Invalid attestation",
|
||||||
debug "attestationPool:add:notValidate",
|
|
||||||
attestationData = shortLog(attestation.data),
|
attestationData = shortLog(attestation.data),
|
||||||
validatorIndex = get_attesting_indices(state, attestation.data, attestation.aggregation_bits, cache),
|
|
||||||
current_epoch = get_current_epoch(state),
|
current_epoch = get_current_epoch(state),
|
||||||
target_epoch = attestation.data.target.epoch,
|
target_epoch = attestation.data.target.epoch,
|
||||||
stateSlot = state.slot
|
stateSlot = state.slot
|
||||||
|
@ -220,15 +186,16 @@ proc add*(pool: var AttestationPool,
|
||||||
if not found:
|
if not found:
|
||||||
# Attestations in the pool that are a subset of the new attestation
|
# Attestations in the pool that are a subset of the new attestation
|
||||||
# can now be removed per same logic as above
|
# 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(
|
a.validations.keepItIf(
|
||||||
if it.aggregation_bits.isSubsetOf(validation.aggregation_bits):
|
not 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)
|
|
||||||
|
|
||||||
a.validations.add(validation)
|
a.validations.add(validation)
|
||||||
pool.updateLatestVotes(state, attestationSlot, participants, a.blck)
|
pool.updateLatestVotes(state, attestationSlot, participants, a.blck)
|
||||||
|
@ -236,7 +203,8 @@ proc add*(pool: var AttestationPool,
|
||||||
info "Attestation resolved",
|
info "Attestation resolved",
|
||||||
attestationData = shortLog(attestation.data),
|
attestationData = shortLog(attestation.data),
|
||||||
validations = a.validations.len(),
|
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),
|
current_epoch = get_current_epoch(state),
|
||||||
target_epoch = attestation.data.target.epoch,
|
target_epoch = attestation.data.target.epoch,
|
||||||
stateSlot = state.slot
|
stateSlot = state.slot
|
||||||
|
@ -246,33 +214,32 @@ proc add*(pool: var AttestationPool,
|
||||||
break
|
break
|
||||||
|
|
||||||
if not found:
|
if not found:
|
||||||
if (let blck = pool.blockPool.getOrResolve(
|
slotData.attestations.add(AttestationEntry(
|
||||||
attestation.data.beacon_block_root); blck != nil):
|
data: attestation.data,
|
||||||
slotData.attestations.add(AttestationEntry(
|
blck: blck,
|
||||||
data: attestation.data,
|
validations: @[validation]
|
||||||
blck: blck,
|
))
|
||||||
validations: @[validation]
|
pool.updateLatestVotes(state, attestationSlot, participants, blck)
|
||||||
))
|
|
||||||
pool.updateLatestVotes(state, attestationSlot, participants, blck)
|
|
||||||
|
|
||||||
info "Attestation resolved",
|
info "Attestation resolved",
|
||||||
attestationData = shortLog(attestation.data),
|
attestationData = shortLog(attestation.data),
|
||||||
validatorIndex = get_attesting_indices(state, attestation.data, attestation.aggregation_bits, cache),
|
validatorIndex = get_attesting_indices(
|
||||||
current_epoch = get_current_epoch(state),
|
state, attestation.data, attestation.aggregation_bits, cache),
|
||||||
target_epoch = attestation.data.target.epoch,
|
current_epoch = get_current_epoch(state),
|
||||||
stateSlot = state.slot,
|
target_epoch = attestation.data.target.epoch,
|
||||||
validations = 1
|
stateSlot = state.slot,
|
||||||
|
validations = 1
|
||||||
|
|
||||||
else:
|
proc addUnresolved*(pool: var AttestationPool, attestation: Attestation) =
|
||||||
pool.unresolved[attestation.data.beacon_block_root] =
|
pool.unresolved[attestation.data.beacon_block_root] =
|
||||||
UnresolvedAttestation(
|
UnresolvedAttestation(
|
||||||
attestation: attestation,
|
attestation: attestation,
|
||||||
)
|
)
|
||||||
|
|
||||||
proc getAttestationsForBlock*(
|
proc getAttestationsForBlock*(
|
||||||
pool: AttestationPool, state: var BeaconState,
|
pool: AttestationPool, state: BeaconState,
|
||||||
newBlockSlot: Slot): seq[Attestation] =
|
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",
|
debug "Too early for attestations",
|
||||||
newBlockSlot = shortLog(newBlockSlot)
|
newBlockSlot = shortLog(newBlockSlot)
|
||||||
return
|
return
|
||||||
|
@ -313,14 +280,21 @@ proc getAttestationsForBlock*(
|
||||||
signature: a.validations[0].aggregate_signature
|
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
|
# 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
|
# include only such attestations that will not cause block validation
|
||||||
# to fail. How this interacts with voting and the acceptance of
|
# to fail. How this interacts with voting and the acceptance of
|
||||||
# attestations into the pool in general is an open question that needs
|
# attestations into the pool in general is an open question that needs
|
||||||
# revisiting - for example, when attestations are added, against which
|
# revisiting - for example, when attestations are added, against which
|
||||||
# state should they be validated, if at all?
|
# state should they be validated, if at all?
|
||||||
if not process_attestation(
|
# TODO we're checking signatures here every time which is very slow - this
|
||||||
state, attestation, {skipValidation, nextSlot}, cache):
|
# 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
|
continue
|
||||||
|
|
||||||
for v in a.validations[1..^1]:
|
for v in a.validations[1..^1]:
|
||||||
|
@ -350,26 +324,28 @@ proc getAttestationsForTargetEpoch*(
|
||||||
for s in begin_slot .. end_slot_minus1:
|
for s in begin_slot .. end_slot_minus1:
|
||||||
result.add getAttestationsForBlock(pool, state, s.Slot)
|
result.add getAttestationsForBlock(pool, state, s.Slot)
|
||||||
|
|
||||||
proc resolve*(pool: var AttestationPool, state: BeaconState) =
|
proc resolve*(pool: var AttestationPool, cache: var StateData) =
|
||||||
var done: seq[Eth2Digest]
|
var
|
||||||
var resolved: seq[Attestation]
|
done: seq[Eth2Digest]
|
||||||
|
resolved: seq[tuple[blck: BlockRef, attestation: Attestation]]
|
||||||
|
|
||||||
for k, v in pool.unresolved.mpairs():
|
for k, v in pool.unresolved.mpairs():
|
||||||
let attestation_slot = get_attestation_data_slot(state, v.attestation.data)
|
if (let blck = pool.blockPool.getRef(k); not blck.isNil()):
|
||||||
if v.tries > 8 or attestation_slot < pool.startingSlot:
|
resolved.add((blck, v.attestation))
|
||||||
|
done.add(k)
|
||||||
|
elif v.tries > 8:
|
||||||
done.add(k)
|
done.add(k)
|
||||||
else:
|
else:
|
||||||
if pool.blockPool.get(k).isSome():
|
inc v.tries
|
||||||
resolved.add(v.attestation)
|
|
||||||
done.add(k)
|
|
||||||
else:
|
|
||||||
inc v.tries
|
|
||||||
|
|
||||||
for k in done:
|
for k in done:
|
||||||
pool.unresolved.del(k)
|
pool.unresolved.del(k)
|
||||||
|
|
||||||
for a in resolved:
|
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*(
|
proc latestAttestation*(
|
||||||
pool: AttestationPool, pubKey: ValidatorPubKey): BlockRef =
|
pool: AttestationPool, pubKey: ValidatorPubKey): BlockRef =
|
||||||
|
|
|
@ -271,22 +271,21 @@ proc getAttachedValidator(
|
||||||
|
|
||||||
proc updateHead(node: BeaconNode, slot: Slot): BlockRef =
|
proc updateHead(node: BeaconNode, slot: Slot): BlockRef =
|
||||||
# Use head state for attestation resolution below
|
# 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
|
# Check pending attestations - maybe we found some blocks for them
|
||||||
debug "Preparing for fork choice",
|
node.attestationPool.resolve(node.stateCache)
|
||||||
stateRoot = shortLog(root),
|
|
||||||
connectedPeers = node.network.peersCount,
|
# TODO move all of this logic to BlockPool
|
||||||
stateSlot = shortLog(state.slot),
|
|
||||||
stateEpoch = shortLog(state.slot.computeEpochOfSlot)
|
|
||||||
|
|
||||||
let
|
let
|
||||||
justifiedHead = node.blockPool.latestJustifiedBlock()
|
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
|
# TODO slot number is wrong here, it should be the start of the epoch that
|
||||||
# got finalized:
|
# got finalized:
|
||||||
# https://github.com/ethereum/eth2.0-specs/issues/768
|
# 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)):
|
BlockSlot(blck: justifiedHead, slot: justifiedHead.slot)):
|
||||||
|
|
||||||
lmdGhost(node.attestationPool, state, justifiedHead)
|
lmdGhost(node.attestationPool, state, justifiedHead)
|
||||||
|
|
||||||
info "Fork chosen",
|
info "Fork chosen",
|
||||||
newHeadSlot = shortLog(newHead.slot),
|
newHeadSlot = shortLog(newHead.slot),
|
||||||
newHeadEpoch = shortLog(newHead.slot.computeEpochOfSlot),
|
newHeadEpoch = shortLog(newHead.slot.computeEpochOfSlot),
|
||||||
|
@ -414,37 +414,30 @@ proc onAttestation(node: BeaconNode, attestation: Attestation) =
|
||||||
attestationData = shortLog(attestation.data),
|
attestationData = shortLog(attestation.data),
|
||||||
signature = shortLog(attestation.signature)
|
signature = shortLog(attestation.signature)
|
||||||
|
|
||||||
let
|
if (let attestedBlock = node.blockPool.getOrResolve(
|
||||||
wallSlot = node.beaconClock.now().toSlot()
|
attestation.data.beacon_block_root); attestedBlock != nil):
|
||||||
head = node.blockPool.head
|
let
|
||||||
|
wallSlot = node.beaconClock.now().toSlot()
|
||||||
|
head = node.blockPool.head
|
||||||
|
|
||||||
if not wallSlot.afterGenesis or wallSlot.slot < head.blck.slot:
|
if not wallSlot.afterGenesis or wallSlot.slot < head.blck.slot:
|
||||||
warn "Received attestation before genesis or head - clock is wrong?",
|
warn "Received attestation before genesis or head - clock is wrong?",
|
||||||
afterGenesis = wallSlot.afterGenesis,
|
afterGenesis = wallSlot.afterGenesis,
|
||||||
wallSlot = shortLog(wallSlot.slot),
|
wallSlot = shortLog(wallSlot.slot),
|
||||||
headSlot = shortLog(head.blck.slot)
|
headSlot = shortLog(head.blck.slot)
|
||||||
return
|
return
|
||||||
|
|
||||||
# TODO seems reasonable to use the latest head state here.. needs thinking
|
# 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
|
# though - maybe we should use the state from the block pointed to by
|
||||||
# the attestation for some of the check? Consider interop with block
|
# the attestation for some of the check? Consider interop with block
|
||||||
# production!
|
# production!
|
||||||
node.blockPool.withState(node.stateCache,
|
let
|
||||||
BlockSlot(blck: head.blck, slot: wallSlot.slot)):
|
bs = BlockSlot(blck: head.blck, slot: wallSlot.slot)
|
||||||
var stateCache = get_empty_per_epoch_cache()
|
|
||||||
node.attestationPool.add(state, attestation)
|
|
||||||
|
|
||||||
debug "Attestation received 2",
|
node.blockPool.withState(node.stateCache, bs):
|
||||||
start_attestation_data_slot =
|
node.attestationPool.add(state, attestedBlock, attestation)
|
||||||
get_attestation_data_slot(state, attestation.data),
|
else:
|
||||||
indexed_attesters =
|
node.attestationPool.addUnresolved(attestation)
|
||||||
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)
|
|
||||||
|
|
||||||
proc onBeaconBlock(node: BeaconNode, blck: BeaconBlock) =
|
proc onBeaconBlock(node: BeaconNode, blck: BeaconBlock) =
|
||||||
# We received a block but don't know much about it yet - in particular, we
|
# 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),
|
attestationHeadRoot = shortLog(attestationHead.blck.root),
|
||||||
attestationSlot = shortLog(slot)
|
attestationSlot = shortLog(slot)
|
||||||
|
|
||||||
|
|
||||||
# Collect data to send before node.stateCache grows stale
|
# Collect data to send before node.stateCache grows stale
|
||||||
var attestations: seq[tuple[
|
var attestations: seq[tuple[
|
||||||
data: AttestationData, committeeLen, indexInCommittee: int,
|
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.
|
# 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
|
# In case blocks went missing, this means advancing past the latest block
|
||||||
# using empty slots as fillers.
|
# 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):
|
node.blockPool.withState(node.stateCache, attestationHead):
|
||||||
var cache = get_empty_per_epoch_cache()
|
var cache = get_empty_per_epoch_cache()
|
||||||
let epoch = compute_epoch_of_slot(slot)
|
let
|
||||||
for committee_index in 0'u64 ..< get_committee_count(state, epoch):
|
epoch = compute_epoch_of_slot(slot)
|
||||||
## TODO verify that this is the correct mapping; it's consistent with
|
committees_per_slot = get_committee_count(state, epoch) div SLOTS_PER_EPOCH
|
||||||
## other code
|
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
|
let
|
||||||
shard = committee_index mod SHARD_COUNT
|
shard = Shard((slot_start_shard + i) mod SHARD_COUNT)
|
||||||
shard2 = (committee_index + get_start_shard(state, epoch)) mod SHARD_COUNT
|
committee = get_crosslink_committee(state, epoch, shard, cache)
|
||||||
committee = get_crosslink_committee(state, epoch, shard2, cache)
|
|
||||||
for i, validatorIdx in committee:
|
for i, validatorIdx in committee:
|
||||||
let validator = node.getAttachedValidator(state, validatorIdx)
|
let validator = node.getAttachedValidator(state, validatorIdx)
|
||||||
if validator != nil:
|
if validator != nil:
|
||||||
let ad = makeAttestationData(state, shard2, blck.root)
|
let ad = makeAttestationData(state, shard, blck.root)
|
||||||
attestations.add (
|
attestations.add((ad, committee.len, i, validator))
|
||||||
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
|
|
||||||
|
|
||||||
for a in attestations:
|
for a in attestations:
|
||||||
traceAsyncErrors sendAttestation(
|
traceAsyncErrors sendAttestation(
|
||||||
|
@ -543,35 +535,10 @@ proc handleProposal(node: BeaconNode, head: BlockRef, slot: Slot):
|
||||||
# revisit this - we should be able to advance behind
|
# revisit this - we should be able to advance behind
|
||||||
var cache = get_empty_per_epoch_cache()
|
var cache = get_empty_per_epoch_cache()
|
||||||
node.blockPool.withState(node.stateCache, BlockSlot(blck: head, slot: slot)):
|
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
|
let
|
||||||
proposerIdx = get_beacon_proposer_index(state, cache)
|
proposerIdx = get_beacon_proposer_index(state, cache)
|
||||||
validator = node.getAttachedValidator(state, proposerIdx)
|
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:
|
if validator != nil:
|
||||||
return await proposeBlock(node, validator, head, slot)
|
return await proposeBlock(node, validator, head, slot)
|
||||||
|
|
||||||
|
|
|
@ -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
|
# 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 =
|
stateCache: var StateCache): bool =
|
||||||
## Check that an attestation follows the rules of being included in the state
|
## 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
|
## 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
|
let data = attestation.data
|
||||||
|
|
||||||
debug "process_attestation: beginning",
|
trace "process_attestation: beginning",
|
||||||
attestation=attestation
|
attestation=attestation
|
||||||
|
|
||||||
if not (data.crosslink.shard < SHARD_COUNT):
|
if not (data.crosslink.shard < SHARD_COUNT):
|
||||||
|
@ -507,13 +508,6 @@ proc process_attestation*(
|
||||||
state_slot = shortLog(stateSlot))
|
state_slot = shortLog(stateSlot))
|
||||||
return
|
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
|
# Check FFG data, crosslink data, and signature
|
||||||
let ffg_check_data = (data.source.epoch, data.source.root, data.target.epoch)
|
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])):
|
hash_tree_root(state.current_crosslinks[data.crosslink.shard])):
|
||||||
warn("Crosslink shard's current crosslinks not matching crosslink parent root")
|
warn("Crosslink shard's current crosslinks not matching crosslink parent root")
|
||||||
return
|
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:
|
else:
|
||||||
if not (ffg_check_data == (state.previous_justified_checkpoint.epoch,
|
if not (ffg_check_data == (state.previous_justified_checkpoint.epoch,
|
||||||
state.previous_justified_checkpoint.root, get_previous_epoch(state))):
|
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")
|
warn("Crosslink shard's previous crosslinks not matching crosslink parent root")
|
||||||
return
|
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):
|
let parent_crosslink = if data.target.epoch == get_current_epoch(state):
|
||||||
state.current_crosslinks[data.crosslink.shard]
|
state.current_crosslinks[data.crosslink.shard]
|
||||||
else:
|
else:
|
||||||
|
@ -583,43 +567,71 @@ proc process_attestation*(
|
||||||
|
|
||||||
true
|
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*(
|
proc makeAttestationData*(
|
||||||
state: BeaconState, shard_offset: uint64,
|
state: BeaconState, shard: uint64,
|
||||||
beacon_block_root: Eth2Digest): AttestationData =
|
beacon_block_root: Eth2Digest): AttestationData =
|
||||||
## Fine points:
|
## Create an attestation / vote for the block `beacon_block_root` using the
|
||||||
## Head must be the head state during the slot that validator is
|
## data in `state` to fill in the rest of the fields.
|
||||||
## part of committee - notably, it can't be a newer or older state (!)
|
## `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
|
let
|
||||||
epoch_start_slot = compute_start_slot_of_epoch(compute_epoch_of_slot(state.slot))
|
current_epoch = get_current_epoch(state)
|
||||||
#shard = (shard_offset + get_start_shard(state,
|
start_slot = compute_start_slot_of_epoch(current_epoch)
|
||||||
# compute_epoch_of_slot(state.slot))) mod SHARD_COUNT
|
epoch_boundary_block_root =
|
||||||
shard = shard_offset
|
if start_slot == state.slot: beacon_block_root
|
||||||
# TODO incorrect epoch for wraparound cases
|
else: get_block_root_at_slot(state, start_slot)
|
||||||
target_epoch = compute_epoch_of_slot(state.slot)
|
parent_crosslink_end_epoch = state.current_crosslinks[shard].end_epoch
|
||||||
# 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
|
|
||||||
|
|
||||||
AttestationData(
|
AttestationData(
|
||||||
beacon_block_root: beacon_block_root,
|
beacon_block_root: beacon_block_root,
|
||||||
source: state.current_justified_checkpoint,
|
source: state.current_justified_checkpoint,
|
||||||
target: Checkpoint(
|
target: Checkpoint(
|
||||||
root: target_root,
|
epoch: current_epoch,
|
||||||
epoch: target_epoch
|
root: epoch_boundary_block_root
|
||||||
),
|
),
|
||||||
crosslink: Crosslink(
|
crosslink: Crosslink(
|
||||||
shard: shard,
|
shard: shard,
|
||||||
parent_root: hash_tree_root(state.current_crosslinks[shard]),
|
parent_root: hash_tree_root(state.current_crosslinks[shard]),
|
||||||
start_epoch: state.current_crosslinks[shard].end_epoch,
|
start_epoch: parent_crosslink_end_epoch,
|
||||||
end_epoch: target_epoch,
|
end_epoch: min(
|
||||||
|
current_epoch, parent_crosslink_end_epoch + MAX_EPOCHS_PER_CROSSLINK),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -265,7 +265,7 @@ proc processAttestations*(
|
||||||
notice "Attestation: too many!", attestations = blck.body.attestations.len
|
notice "Attestation: too many!", attestations = blck.body.attestations.len
|
||||||
return false
|
return false
|
||||||
|
|
||||||
debug "in processAttestations, not processed attestations",
|
trace "in processAttestations, not processed attestations",
|
||||||
attestations_len = blck.body.attestations.len()
|
attestations_len = blck.body.attestations.len()
|
||||||
|
|
||||||
if not blck.body.attestations.allIt(process_attestation(state, it, flags, stateCache)):
|
if not blck.body.attestations.allIt(process_attestation(state, it, flags, stateCache)):
|
||||||
|
@ -275,7 +275,7 @@ proc processAttestations*(
|
||||||
# Apply the attestations
|
# Apply the attestations
|
||||||
var committee_count_cache = initTable[Epoch, uint64]()
|
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()
|
attestations_len = blck.body.attestations.len()
|
||||||
|
|
||||||
var cache = get_empty_per_epoch_cache()
|
var cache = get_empty_per_epoch_cache()
|
||||||
|
@ -305,7 +305,7 @@ proc processAttestations*(
|
||||||
else:
|
else:
|
||||||
state.previous_epoch_attestations.add(pending_attestation)
|
state.previous_epoch_attestations.add(pending_attestation)
|
||||||
|
|
||||||
debug "processAttestations",
|
trace "processAttestations",
|
||||||
target_epoch=attestation.data.target.epoch,
|
target_epoch=attestation.data.target.epoch,
|
||||||
current_epoch= get_current_epoch(state),
|
current_epoch= get_current_epoch(state),
|
||||||
current_epoch_attestations_len=len(get_attesting_indices(state, state.current_epoch_attestations, cache)),
|
current_epoch_attestations_len=len(get_attesting_indices(state, state.current_epoch_attestations, cache)),
|
||||||
|
|
|
@ -517,20 +517,20 @@ proc process_final_updates(state: var BeaconState) =
|
||||||
SHARD_COUNT
|
SHARD_COUNT
|
||||||
|
|
||||||
# Rotate current/previous epoch attestations
|
# Rotate current/previous epoch attestations
|
||||||
debug "Rotating epoch attestations",
|
trace "Rotating epoch attestations",
|
||||||
current_epoch = get_current_epoch(state)
|
current_epoch = get_current_epoch(state)
|
||||||
|
|
||||||
state.previous_epoch_attestations = state.current_epoch_attestations
|
state.previous_epoch_attestations = state.current_epoch_attestations
|
||||||
state.current_epoch_attestations = @[]
|
state.current_epoch_attestations = @[]
|
||||||
|
|
||||||
debug "Rotated epoch attestations",
|
trace "Rotated epoch attestations",
|
||||||
current_epoch = get_current_epoch(state)
|
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
|
# 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 process_epoch*(state: var BeaconState) =
|
||||||
# @proc are placeholders
|
# @proc are placeholders
|
||||||
|
|
||||||
debug "process_epoch",
|
trace "process_epoch",
|
||||||
current_epoch = get_current_epoch(state)
|
current_epoch = get_current_epoch(state)
|
||||||
|
|
||||||
var per_epoch_cache = get_empty_per_epoch_cache()
|
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
|
# 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)
|
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)
|
current_epoch = get_current_epoch(state)
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.8.2/specs/core/0_beacon-chain.md#crosslinks
|
# https://github.com/ethereum/eth2.0-specs/blob/v0.8.2/specs/core/0_beacon-chain.md#crosslinks
|
||||||
|
|
|
@ -64,12 +64,12 @@ proc process_slots*(state: var BeaconState, slot: Slot) =
|
||||||
if (state.slot + 1) mod SLOTS_PER_EPOCH == 0:
|
if (state.slot + 1) mod SLOTS_PER_EPOCH == 0:
|
||||||
# Note: Genesis epoch = 0, no need to test if before Genesis
|
# Note: Genesis epoch = 0, no need to test if before Genesis
|
||||||
process_epoch(state)
|
process_epoch(state)
|
||||||
debug "process_slots: Incrementing slot",
|
trace "process_slots: Incrementing slot",
|
||||||
state_slot_now = state.slot,
|
state_slot_now = state.slot,
|
||||||
state_slot_next = state.slot + 1,
|
state_slot_next = state.slot + 1,
|
||||||
cur_epoch = get_current_epoch(state)
|
cur_epoch = get_current_epoch(state)
|
||||||
state.slot += 1
|
state.slot += 1
|
||||||
debug "process_slots: Incremented slot",
|
trace "process_slots: Incremented slot",
|
||||||
cur_epoch = get_current_epoch(state)
|
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
|
# 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:
|
if (state.data.slot + 1) mod SLOTS_PER_EPOCH == 0:
|
||||||
# Note: Genesis epoch = 0, no need to test if before Genesis
|
# Note: Genesis epoch = 0, no need to test if before Genesis
|
||||||
process_epoch(state.data)
|
process_epoch(state.data)
|
||||||
debug "process_slots_HashedBeaconState_: Incrementing slot",
|
trace "process_slots_HashedBeaconState_: Incrementing slot",
|
||||||
state_slot_now = state.data.slot,
|
state_slot_now = state.data.slot,
|
||||||
state_slot_next = state.data.slot + 1,
|
state_slot_next = state.data.slot + 1,
|
||||||
cur_epoch = get_current_epoch(state.data)
|
cur_epoch = get_current_epoch(state.data)
|
||||||
|
|
|
@ -21,7 +21,7 @@ mkdir -p "${BUILD_OUTPUTS_DIR}"
|
||||||
DEFS="-d:chronicles_log_level=DEBUG "
|
DEFS="-d:chronicles_log_level=DEBUG "
|
||||||
DEFS+="-d:SHARD_COUNT=${SHARD_COUNT:-16} " # Spec default: 1024
|
DEFS+="-d:SHARD_COUNT=${SHARD_COUNT:-16} " # Spec default: 1024
|
||||||
DEFS+="-d:SLOTS_PER_EPOCH=${SLOTS_PER_EPOCH:-16} " # Spec default: 64
|
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_NUM=$(( NUM_VALIDATORS - 1 ))
|
||||||
LAST_VALIDATOR="$VALIDATORS_DIR/v$(printf '%07d' $LAST_VALIDATOR_NUM).deposit.json"
|
LAST_VALIDATOR="$VALIDATORS_DIR/v$(printf '%07d' $LAST_VALIDATOR_NUM).deposit.json"
|
||||||
|
|
|
@ -15,7 +15,7 @@ cd - &>/dev/null
|
||||||
: ${BUILD_OUTPUTS_DIR:="$GIT_ROOT/build"}
|
: ${BUILD_OUTPUTS_DIR:="$GIT_ROOT/build"}
|
||||||
|
|
||||||
NUM_VALIDATORS=${VALIDATORS:-1000}
|
NUM_VALIDATORS=${VALIDATORS:-1000}
|
||||||
NUM_NODES=${NODES:-2}
|
NUM_NODES=${NODES:-4}
|
||||||
NUM_MISSING_NODES=${MISSING_NODES:-0}
|
NUM_MISSING_NODES=${MISSING_NODES:-0}
|
||||||
|
|
||||||
SIMULATION_DIR="${SIM_ROOT}/data"
|
SIMULATION_DIR="${SIM_ROOT}/data"
|
||||||
|
|
|
@ -44,7 +44,7 @@ suite "Attestation pool processing" & preset():
|
||||||
attestation = makeAttestation(
|
attestation = makeAttestation(
|
||||||
state.data.data, state.blck.root, crosslink_committee[0])
|
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?
|
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])
|
state.data.data, state.blck.root, cc1[0])
|
||||||
|
|
||||||
# test reverse order
|
# test reverse order
|
||||||
pool.add(state.data.data, attestation1)
|
pool.add(state.data.data, state.blck, attestation1)
|
||||||
pool.add(state.data.data, attestation0)
|
pool.add(state.data.data, state.blck, attestation0)
|
||||||
|
|
||||||
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot) # minus 1?
|
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot) # minus 1?
|
||||||
|
|
||||||
|
@ -96,8 +96,8 @@ suite "Attestation pool processing" & preset():
|
||||||
attestation1 = makeAttestation(
|
attestation1 = makeAttestation(
|
||||||
state.data.data, state.blck.root, cc0[1])
|
state.data.data, state.blck.root, cc0[1])
|
||||||
|
|
||||||
pool.add(state.data.data, attestation0)
|
pool.add(state.data.data, state.blck, attestation0)
|
||||||
pool.add(state.data.data, attestation1)
|
pool.add(state.data.data, state.blck, attestation1)
|
||||||
|
|
||||||
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot) # minus 1?
|
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot) # minus 1?
|
||||||
|
|
||||||
|
@ -122,8 +122,8 @@ suite "Attestation pool processing" & preset():
|
||||||
|
|
||||||
attestation0.combine(attestation1, {skipValidation})
|
attestation0.combine(attestation1, {skipValidation})
|
||||||
|
|
||||||
pool.add(state.data.data, attestation0)
|
pool.add(state.data.data, state.blck, attestation0)
|
||||||
pool.add(state.data.data, attestation1)
|
pool.add(state.data.data, state.blck, attestation1)
|
||||||
|
|
||||||
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot) # minus 1?
|
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot) # minus 1?
|
||||||
|
|
||||||
|
@ -147,8 +147,8 @@ suite "Attestation pool processing" & preset():
|
||||||
|
|
||||||
attestation0.combine(attestation1, {skipValidation})
|
attestation0.combine(attestation1, {skipValidation})
|
||||||
|
|
||||||
pool.add(state.data.data, attestation1)
|
pool.add(state.data.data, state.blck, attestation1)
|
||||||
pool.add(state.data.data, attestation0)
|
pool.add(state.data.data, state.blck, attestation0)
|
||||||
|
|
||||||
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot) # minus 1?
|
process_slots(state.data, MIN_ATTESTATION_INCLUSION_DELAY.Slot) # minus 1?
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue