avoid replaying long empty slots on old votes (#1304)

* avoid replaying long empty slots on old votes

* fixup!

* fixup!

* fixup!
This commit is contained in:
Jacek Sieka 2020-07-13 16:58:38 +02:00 committed by GitHub
parent 0be77f9cbc
commit 300e0d57c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 0 deletions

View File

@ -74,6 +74,31 @@ proc aggregate_attestations*(
none(AggregateAndProof)
proc isValidAttestationSlot(
pool: AttestationPool, attestationSlot: Slot, attestationBlck: BlockRef): bool =
# If we allow voting for very old blocks, the state transaction below will go
# nuts and keep processing empty slots
logScope:
attestationSlot
attestationBlck = shortLog(attestationBlck)
if not (attestationBlck.slot > pool.blockPool.finalizedHead.slot):
debug "voting for already-finalized block"
return false
# we'll also cap it at 4 epochs which is somewhat arbitrary, but puts an
# upper bound on the processing done to validate the attestation
# TODO revisit with less arbitrary approach
if not (attestationSlot >= attestationBlck.slot):
debug "voting for block that didn't exist at the time"
return false
if not ((attestationSlot - attestationBlck.slot) <= uint64(4 * SLOTS_PER_EPOCH)):
debug "voting for very old block"
return false
true
# https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/specs/phase0/p2p-interface.md#attestation-subnets
proc isValidAttestation*(
pool: var AttestationPool, attestation: Attestation, current_slot: Slot,
@ -132,6 +157,10 @@ proc isValidAttestation*(
pool.blockPool.addMissing(attestation.data.beacon_block_root)
return false
if not isValidAttestationSlot(pool, attestation.data.slot, attestationBlck):
# Not in spec - check that rewinding to the state is sane
return false
pool.blockPool.withState(
pool.blockPool.tmpState,
BlockSlot(blck: attestationBlck, slot: attestation.data.slot)):
@ -222,6 +251,10 @@ proc isValidAggregatedAttestation*(
debug "isValidAggregatedAttestation: attestation has no or invalid aggregation bits"
return false
if not isValidAttestationSlot(pool, aggregate.data.slot, attestationBlck):
# Not in spec - check that rewinding to the state is sane
return false
# [REJECT] aggregate_and_proof.selection_proof selects the validator as an
# aggregator for the slot -- i.e. is_aggregator(state, aggregate.data.slot,
# aggregate.data.index, aggregate_and_proof.selection_proof) returns True.

View File

@ -694,6 +694,7 @@ proc installBeaconApiHandlers(rpcServer: RpcServer, node: BeaconNode) =
root: Option[Eth2Digest]) -> StringOfJson:
requireOneOf(slot, root)
if slot.isSome:
# TODO sanity check slot so that it doesn't cause excessive rewinding
let blk = node.blockPool.head.blck.atSlot(slot.get)
node.blockPool.withState(node.blockPool.tmpState, blk):
return jsonResult(state)