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:
parent
0be77f9cbc
commit
300e0d57c1
|
@ -74,6 +74,31 @@ proc aggregate_attestations*(
|
||||||
|
|
||||||
none(AggregateAndProof)
|
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
|
# https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/specs/phase0/p2p-interface.md#attestation-subnets
|
||||||
proc isValidAttestation*(
|
proc isValidAttestation*(
|
||||||
pool: var AttestationPool, attestation: Attestation, current_slot: Slot,
|
pool: var AttestationPool, attestation: Attestation, current_slot: Slot,
|
||||||
|
@ -132,6 +157,10 @@ proc isValidAttestation*(
|
||||||
pool.blockPool.addMissing(attestation.data.beacon_block_root)
|
pool.blockPool.addMissing(attestation.data.beacon_block_root)
|
||||||
return false
|
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.withState(
|
||||||
pool.blockPool.tmpState,
|
pool.blockPool.tmpState,
|
||||||
BlockSlot(blck: attestationBlck, slot: attestation.data.slot)):
|
BlockSlot(blck: attestationBlck, slot: attestation.data.slot)):
|
||||||
|
@ -222,6 +251,10 @@ proc isValidAggregatedAttestation*(
|
||||||
debug "isValidAggregatedAttestation: attestation has no or invalid aggregation bits"
|
debug "isValidAggregatedAttestation: attestation has no or invalid aggregation bits"
|
||||||
return false
|
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
|
# [REJECT] aggregate_and_proof.selection_proof selects the validator as an
|
||||||
# aggregator for the slot -- i.e. is_aggregator(state, aggregate.data.slot,
|
# aggregator for the slot -- i.e. is_aggregator(state, aggregate.data.slot,
|
||||||
# aggregate.data.index, aggregate_and_proof.selection_proof) returns True.
|
# aggregate.data.index, aggregate_and_proof.selection_proof) returns True.
|
||||||
|
|
|
@ -694,6 +694,7 @@ proc installBeaconApiHandlers(rpcServer: RpcServer, node: BeaconNode) =
|
||||||
root: Option[Eth2Digest]) -> StringOfJson:
|
root: Option[Eth2Digest]) -> StringOfJson:
|
||||||
requireOneOf(slot, root)
|
requireOneOf(slot, root)
|
||||||
if slot.isSome:
|
if slot.isSome:
|
||||||
|
# TODO sanity check slot so that it doesn't cause excessive rewinding
|
||||||
let blk = node.blockPool.head.blck.atSlot(slot.get)
|
let blk = node.blockPool.head.blck.atSlot(slot.get)
|
||||||
node.blockPool.withState(node.blockPool.tmpState, blk):
|
node.blockPool.withState(node.blockPool.tmpState, blk):
|
||||||
return jsonResult(state)
|
return jsonResult(state)
|
||||||
|
|
Loading…
Reference in New Issue