2019-02-19 23:35:02 +00:00
|
|
|
# beacon_chain
|
2022-02-16 22:24:44 +00:00
|
|
|
# Copyright (c) 2018-2022 Status Research & Development GmbH
|
2019-02-19 23:35:02 +00:00
|
|
|
# Licensed and distributed under either of
|
2019-11-25 15:30:02 +00:00
|
|
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
|
|
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
2019-02-19 23:35:02 +00:00
|
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
|
2019-11-14 10:47:55 +00:00
|
|
|
{.used.}
|
|
|
|
|
2019-02-19 23:35:02 +00:00
|
|
|
import
|
2021-04-12 20:25:09 +00:00
|
|
|
std/sequtils,
|
2021-01-25 18:45:48 +00:00
|
|
|
# Status lib
|
2021-04-12 20:25:09 +00:00
|
|
|
unittest2,
|
2020-08-27 07:34:12 +00:00
|
|
|
chronicles, chronos,
|
2020-04-29 11:44:07 +00:00
|
|
|
stew/byteutils,
|
2021-09-17 00:13:52 +00:00
|
|
|
eth/keys, taskpools,
|
2021-01-25 18:45:48 +00:00
|
|
|
# Internal
|
2021-04-26 20:39:44 +00:00
|
|
|
../beacon_chain/gossip_processing/[gossip_validation],
|
2020-07-30 19:18:17 +00:00
|
|
|
../beacon_chain/fork_choice/[fork_choice_types, fork_choice],
|
2021-04-12 20:25:09 +00:00
|
|
|
../beacon_chain/consensus_object_pools/[
|
2021-06-11 17:51:46 +00:00
|
|
|
block_quarantine, blockchain_dag, block_clearance, attestation_pool],
|
2021-08-12 13:08:20 +00:00
|
|
|
../beacon_chain/spec/datatypes/phase0,
|
2021-11-18 12:02:43 +00:00
|
|
|
../beacon_chain/spec/[beaconstate, helpers, state_transition, validator],
|
2021-12-21 18:56:08 +00:00
|
|
|
../beacon_chain/beacon_clock,
|
2021-01-25 18:45:48 +00:00
|
|
|
# Test utilities
|
2021-04-28 16:41:02 +00:00
|
|
|
./testutil, ./testdbutil, ./testblockutil
|
2020-07-09 09:29:32 +00:00
|
|
|
|
2021-01-22 13:29:04 +00:00
|
|
|
func combine(tgt: var Attestation, src: Attestation) =
|
2020-08-15 17:33:58 +00:00
|
|
|
## Combine the signature and participation bitfield, with the assumption that
|
|
|
|
## the same data is being signed - if the signatures overlap, they are not
|
|
|
|
## combined.
|
|
|
|
|
|
|
|
doAssert tgt.data == src.data
|
|
|
|
|
|
|
|
# In a BLS aggregate signature, one needs to count how many times a
|
|
|
|
# particular public key has been added - since we use a single bit per key, we
|
|
|
|
# can only it once, thus we can never combine signatures that overlap already!
|
2021-04-12 20:25:09 +00:00
|
|
|
doAssert not tgt.aggregation_bits.overlaps(src.aggregation_bits)
|
2020-08-15 17:33:58 +00:00
|
|
|
|
2021-04-12 20:25:09 +00:00
|
|
|
tgt.aggregation_bits.incl(src.aggregation_bits)
|
|
|
|
|
2022-02-16 22:24:44 +00:00
|
|
|
var agg {.noinit.}: AggregateSignature
|
2021-04-26 20:39:44 +00:00
|
|
|
agg.init(tgt.signature.load().get())
|
|
|
|
agg.aggregate(src.signature.load.get())
|
|
|
|
tgt.signature = agg.finish().toValidatorSig()
|
2020-08-15 17:33:58 +00:00
|
|
|
|
2021-04-09 12:59:24 +00:00
|
|
|
func loadSig(a: Attestation): CookedSig =
|
2021-04-26 20:39:44 +00:00
|
|
|
a.signature.load.get()
|
2021-04-09 12:59:24 +00:00
|
|
|
|
2021-03-09 14:36:17 +00:00
|
|
|
proc pruneAtFinalization(dag: ChainDAGRef, attPool: AttestationPool) =
|
|
|
|
if dag.needStateCachesAndForkChoicePruning():
|
|
|
|
dag.pruneStateCachesDAG()
|
|
|
|
# pool[].prune() # We test logic without attestation pool / fork choice pruning
|
|
|
|
|
2021-04-28 16:41:02 +00:00
|
|
|
suite "Attestation pool processing" & preset():
|
2020-04-29 11:44:07 +00:00
|
|
|
## For now just test that we can compile and execute block processing with
|
|
|
|
## mock data.
|
2019-12-19 14:13:35 +00:00
|
|
|
|
2020-04-29 11:44:07 +00:00
|
|
|
setup:
|
2021-04-12 20:25:09 +00:00
|
|
|
# Genesis state that results in 6 members per committee
|
2020-04-29 11:44:07 +00:00
|
|
|
var
|
2021-12-20 19:20:31 +00:00
|
|
|
validatorMonitor = newClone(ValidatorMonitor.init())
|
|
|
|
dag = init(
|
|
|
|
ChainDAGRef, defaultRuntimeConfig, makeTestDB(SLOTS_PER_EPOCH * 6),
|
|
|
|
validatorMonitor, {})
|
2021-09-17 00:13:52 +00:00
|
|
|
taskpool = Taskpool.new()
|
2021-12-06 09:49:01 +00:00
|
|
|
verifier = BatchVerifier(rng: keys.newRng(), taskpool: taskpool)
|
|
|
|
quarantine = newClone(Quarantine.init())
|
2021-06-01 11:13:40 +00:00
|
|
|
pool = newClone(AttestationPool.init(dag, quarantine))
|
|
|
|
state = newClone(dag.headState)
|
2020-09-07 15:04:33 +00:00
|
|
|
cache = StateCache()
|
2021-10-13 14:24:36 +00:00
|
|
|
info = ForkedEpochInfo()
|
2020-04-29 11:44:07 +00:00
|
|
|
# Slot 0 is a finalized slot - won't be making attestations for it..
|
2020-05-19 15:46:29 +00:00
|
|
|
check:
|
2021-06-11 17:51:46 +00:00
|
|
|
process_slots(
|
2022-03-16 07:20:40 +00:00
|
|
|
dag.cfg, state[], getStateField(state[], slot) + 1, cache, info,
|
2022-01-17 11:19:58 +00:00
|
|
|
{}).isOk()
|
2020-04-29 11:44:07 +00:00
|
|
|
|
2021-04-28 16:41:02 +00:00
|
|
|
test "Can add and retrieve simple attestations" & preset():
|
2020-04-29 11:44:07 +00:00
|
|
|
let
|
|
|
|
# Create an attestation for slot 1!
|
2021-04-12 20:25:09 +00:00
|
|
|
bc0 = get_beacon_committee(
|
2022-03-16 07:20:40 +00:00
|
|
|
state[], getStateField(state[], slot), 0.CommitteeIndex, cache)
|
|
|
|
attestation = makeAttestation(
|
|
|
|
state[], state[].latest_block_root, bc0[0], cache)
|
2020-04-29 11:44:07 +00:00
|
|
|
|
2020-08-27 07:34:12 +00:00
|
|
|
pool[].addAttestation(
|
2021-04-12 20:25:09 +00:00
|
|
|
attestation, @[bc0[0]], attestation.loadSig,
|
2022-01-11 10:01:54 +00:00
|
|
|
attestation.data.slot.start_beacon_time)
|
2019-12-19 14:13:35 +00:00
|
|
|
|
2020-05-19 15:46:29 +00:00
|
|
|
check:
|
2021-04-12 20:25:09 +00:00
|
|
|
# Added attestation, should get it back
|
|
|
|
toSeq(pool[].attestations(none(Slot), none(CommitteeIndex))) ==
|
|
|
|
@[attestation]
|
|
|
|
toSeq(pool[].attestations(
|
|
|
|
some(attestation.data.slot), none(CommitteeIndex))) == @[attestation]
|
|
|
|
toSeq(pool[].attestations(
|
|
|
|
some(attestation.data.slot), some(attestation.data.index.CommitteeIndex))) ==
|
|
|
|
@[attestation]
|
|
|
|
toSeq(pool[].attestations(none(Slot), some(attestation.data.index.CommitteeIndex))) ==
|
|
|
|
@[attestation]
|
|
|
|
toSeq(pool[].attestations(some(
|
|
|
|
attestation.data.slot + 1), none(CommitteeIndex))) == []
|
|
|
|
toSeq(pool[].attestations(
|
|
|
|
none(Slot), some(CommitteeIndex(attestation.data.index + 1)))) == []
|
|
|
|
|
|
|
|
process_slots(
|
2022-03-16 07:20:40 +00:00
|
|
|
defaultRuntimeConfig, state[],
|
|
|
|
getStateField(state[], slot) + MIN_ATTESTATION_INCLUSION_DELAY, cache,
|
2022-01-17 11:19:58 +00:00
|
|
|
info, {}).isOk()
|
2020-04-29 11:44:07 +00:00
|
|
|
|
2022-03-16 07:20:40 +00:00
|
|
|
let attestations = pool[].getAttestationsForBlock(state[], cache)
|
2019-12-19 14:13:35 +00:00
|
|
|
|
2020-04-29 11:44:07 +00:00
|
|
|
check:
|
|
|
|
attestations.len == 1
|
2021-04-12 20:25:09 +00:00
|
|
|
pool[].getAggregatedAttestation(1.Slot, 0.CommitteeIndex).isSome()
|
|
|
|
|
|
|
|
let
|
|
|
|
root1 = addTestBlock(
|
2022-03-16 07:20:40 +00:00
|
|
|
state[], cache, attestations = attestations,
|
2021-11-18 12:02:43 +00:00
|
|
|
nextSlot = false).phase0Data.root
|
2021-04-12 20:25:09 +00:00
|
|
|
bc1 = get_beacon_committee(
|
2022-03-16 07:20:40 +00:00
|
|
|
state[], getStateField(state[], slot), 0.CommitteeIndex, cache)
|
|
|
|
att1 = makeAttestation(state[], root1, bc1[0], cache)
|
2020-04-29 11:44:07 +00:00
|
|
|
|
2021-04-12 20:25:09 +00:00
|
|
|
check:
|
2022-03-16 07:20:40 +00:00
|
|
|
withState(state[]): state.latest_block_root == root1
|
2021-11-18 12:02:43 +00:00
|
|
|
|
2021-04-12 20:25:09 +00:00
|
|
|
process_slots(
|
2022-03-16 07:20:40 +00:00
|
|
|
defaultRuntimeConfig, state[],
|
|
|
|
getStateField(state[], slot) + MIN_ATTESTATION_INCLUSION_DELAY, cache,
|
2022-01-17 11:19:58 +00:00
|
|
|
info, {}).isOk()
|
2021-04-12 20:25:09 +00:00
|
|
|
|
2022-03-16 07:20:40 +00:00
|
|
|
withState(state[]): state.latest_block_root == root1
|
2021-11-18 12:02:43 +00:00
|
|
|
|
2021-04-12 20:25:09 +00:00
|
|
|
check:
|
|
|
|
# shouldn't include already-included attestations
|
2022-03-16 07:20:40 +00:00
|
|
|
pool[].getAttestationsForBlock(state[], cache) == []
|
2021-04-12 20:25:09 +00:00
|
|
|
|
|
|
|
pool[].addAttestation(
|
2022-01-11 10:01:54 +00:00
|
|
|
att1, @[bc1[0]], att1.loadSig, att1.data.slot.start_beacon_time)
|
2021-04-12 20:25:09 +00:00
|
|
|
|
|
|
|
check:
|
|
|
|
# but new ones should go in
|
2022-03-16 07:20:40 +00:00
|
|
|
pool[].getAttestationsForBlock(state[], cache).len() == 1
|
2021-04-12 20:25:09 +00:00
|
|
|
|
|
|
|
let
|
2022-03-16 07:20:40 +00:00
|
|
|
att2 = makeAttestation(state[], root1, bc1[1], cache)
|
2021-04-12 20:25:09 +00:00
|
|
|
pool[].addAttestation(
|
2022-01-11 10:01:54 +00:00
|
|
|
att2, @[bc1[1]], att2.loadSig, att2.data.slot.start_beacon_time)
|
2021-04-12 20:25:09 +00:00
|
|
|
|
|
|
|
let
|
2022-03-16 07:20:40 +00:00
|
|
|
combined = pool[].getAttestationsForBlock(state[], cache)
|
2021-04-12 20:25:09 +00:00
|
|
|
|
|
|
|
check:
|
|
|
|
# New attestations should be combined with old attestations
|
|
|
|
combined.len() == 1
|
|
|
|
combined[0].aggregation_bits.countOnes() == 2
|
|
|
|
|
|
|
|
pool[].addAttestation(
|
2021-12-21 18:56:08 +00:00
|
|
|
combined[0], @[bc1[1], bc1[0]], combined[0].loadSig,
|
2022-01-11 10:01:54 +00:00
|
|
|
combined[0].data.slot.start_beacon_time)
|
2021-04-12 20:25:09 +00:00
|
|
|
|
|
|
|
check:
|
|
|
|
# readding the combined attestation shouldn't have an effect
|
2022-03-16 07:20:40 +00:00
|
|
|
pool[].getAttestationsForBlock(state[], cache).len() == 1
|
2021-04-12 20:25:09 +00:00
|
|
|
|
|
|
|
let
|
|
|
|
# Someone votes for a different root
|
2022-03-16 07:20:40 +00:00
|
|
|
att3 = makeAttestation(state[], Eth2Digest(), bc1[2], cache)
|
2021-04-12 20:25:09 +00:00
|
|
|
pool[].addAttestation(
|
2022-01-11 10:01:54 +00:00
|
|
|
att3, @[bc1[2]], att3.loadSig, att3.data.slot.start_beacon_time)
|
2021-04-12 20:25:09 +00:00
|
|
|
|
|
|
|
check:
|
|
|
|
# We should now get both attestations for the block, but the aggregate
|
|
|
|
# should be the one with the most votes
|
2022-03-16 07:20:40 +00:00
|
|
|
pool[].getAttestationsForBlock(state[], cache).len() == 2
|
2021-04-12 20:25:09 +00:00
|
|
|
pool[].getAggregatedAttestation(2.Slot, 0.CommitteeIndex).
|
|
|
|
get().aggregation_bits.countOnes() == 2
|
|
|
|
pool[].getAggregatedAttestation(2.Slot, hash_tree_root(att2.data)).
|
|
|
|
get().aggregation_bits.countOnes() == 2
|
|
|
|
|
|
|
|
let
|
|
|
|
# Someone votes for a different root
|
2022-03-16 07:20:40 +00:00
|
|
|
att4 = makeAttestation(state[], Eth2Digest(), bc1[2], cache)
|
2021-04-12 20:25:09 +00:00
|
|
|
pool[].addAttestation(
|
2022-01-11 10:01:54 +00:00
|
|
|
att4, @[bc1[2]], att3.loadSig, att3.data.slot.start_beacon_time)
|
2021-04-12 20:25:09 +00:00
|
|
|
|
2021-04-28 16:41:02 +00:00
|
|
|
test "Working with aggregates" & preset():
|
2021-04-12 20:25:09 +00:00
|
|
|
let
|
|
|
|
# Create an attestation for slot 1!
|
|
|
|
bc0 = get_beacon_committee(
|
2022-03-16 07:20:40 +00:00
|
|
|
state[], getStateField(state[], slot), 0.CommitteeIndex, cache)
|
2021-04-12 20:25:09 +00:00
|
|
|
|
|
|
|
var
|
2022-03-16 07:20:40 +00:00
|
|
|
att0 = makeAttestation(
|
|
|
|
state[], state[].latest_block_root, bc0[0], cache)
|
2021-04-12 20:25:09 +00:00
|
|
|
att0x = att0
|
2022-03-16 07:20:40 +00:00
|
|
|
att1 = makeAttestation(
|
|
|
|
state[], state[].latest_block_root, bc0[1], cache)
|
|
|
|
att2 = makeAttestation(
|
|
|
|
state[], state[].latest_block_root, bc0[2], cache)
|
|
|
|
att3 = makeAttestation(
|
|
|
|
state[], state[].latest_block_root, bc0[3], cache)
|
2021-04-12 20:25:09 +00:00
|
|
|
|
|
|
|
# Both attestations include member 2 but neither is a subset of the other
|
|
|
|
att0.combine(att2)
|
|
|
|
att1.combine(att2)
|
|
|
|
|
2022-02-25 16:15:39 +00:00
|
|
|
check:
|
|
|
|
not pool[].covers(att0.data, att0.aggregation_bits)
|
|
|
|
|
2021-12-21 18:56:08 +00:00
|
|
|
pool[].addAttestation(
|
2022-01-11 10:01:54 +00:00
|
|
|
att0, @[bc0[0], bc0[2]], att0.loadSig, att0.data.slot.start_beacon_time)
|
2021-12-21 18:56:08 +00:00
|
|
|
pool[].addAttestation(
|
2022-01-11 10:01:54 +00:00
|
|
|
att1, @[bc0[1], bc0[2]], att1.loadSig, att1.data.slot.start_beacon_time)
|
2021-04-12 20:25:09 +00:00
|
|
|
|
|
|
|
check:
|
|
|
|
process_slots(
|
2022-03-16 07:20:40 +00:00
|
|
|
defaultRuntimeConfig, state[],
|
|
|
|
getStateField(state[], slot) + MIN_ATTESTATION_INCLUSION_DELAY, cache,
|
2022-01-17 11:19:58 +00:00
|
|
|
info, {}).isOk()
|
2021-04-12 20:25:09 +00:00
|
|
|
|
|
|
|
check:
|
2022-02-25 16:15:39 +00:00
|
|
|
pool[].covers(att0.data, att0.aggregation_bits)
|
2022-03-16 07:20:40 +00:00
|
|
|
pool[].getAttestationsForBlock(state[], cache).len() == 2
|
2021-04-12 20:25:09 +00:00
|
|
|
# Can get either aggregate here, random!
|
|
|
|
pool[].getAggregatedAttestation(1.Slot, 0.CommitteeIndex).isSome()
|
|
|
|
|
|
|
|
# Add in attestation 3 - both aggregates should now have it added
|
2021-12-21 18:56:08 +00:00
|
|
|
pool[].addAttestation(
|
2022-01-11 10:01:54 +00:00
|
|
|
att3, @[bc0[3]], att3.loadSig, att3.data.slot.start_beacon_time)
|
2021-04-12 20:25:09 +00:00
|
|
|
|
|
|
|
block:
|
2022-03-16 07:20:40 +00:00
|
|
|
let attestations = pool[].getAttestationsForBlock(state[], cache)
|
2021-04-12 20:25:09 +00:00
|
|
|
check:
|
|
|
|
attestations.len() == 2
|
|
|
|
attestations[0].aggregation_bits.countOnes() == 3
|
|
|
|
# Can get either aggregate here, random!
|
|
|
|
pool[].getAggregatedAttestation(1.Slot, 0.CommitteeIndex).isSome()
|
|
|
|
|
|
|
|
# Add in attestation 0 as single - attestation 1 is now a superset of the
|
|
|
|
# aggregates in the pool, so everything else should be removed
|
2021-12-21 18:56:08 +00:00
|
|
|
pool[].addAttestation(
|
2022-01-11 10:01:54 +00:00
|
|
|
att0x, @[bc0[0]], att0x.loadSig, att0x.data.slot.start_beacon_time)
|
2021-04-12 20:25:09 +00:00
|
|
|
|
|
|
|
block:
|
2022-03-16 07:20:40 +00:00
|
|
|
let attestations = pool[].getAttestationsForBlock(state[], cache)
|
2021-04-12 20:25:09 +00:00
|
|
|
check:
|
|
|
|
attestations.len() == 1
|
|
|
|
attestations[0].aggregation_bits.countOnes() == 4
|
|
|
|
pool[].getAggregatedAttestation(1.Slot, 0.CommitteeIndex).isSome()
|
|
|
|
|
2021-04-28 16:41:02 +00:00
|
|
|
test "Everyone voting for something different" & preset():
|
2021-04-12 20:25:09 +00:00
|
|
|
var attestations: int
|
|
|
|
for i in 0..<SLOTS_PER_EPOCH:
|
|
|
|
var root: Eth2Digest
|
|
|
|
root.data[0..<8] = toBytesBE(i.uint64)
|
|
|
|
let
|
|
|
|
bc0 = get_beacon_committee(
|
2022-03-16 07:20:40 +00:00
|
|
|
state[], getStateField(state[], slot), 0.CommitteeIndex, cache)
|
2021-04-12 20:25:09 +00:00
|
|
|
|
|
|
|
for j in 0..<bc0.len():
|
|
|
|
root.data[8..<16] = toBytesBE(j.uint64)
|
2022-03-16 07:20:40 +00:00
|
|
|
let att = makeAttestation(state[], root, bc0[j], cache)
|
2021-12-21 18:56:08 +00:00
|
|
|
pool[].addAttestation(
|
2022-01-11 10:01:54 +00:00
|
|
|
att, @[bc0[j]], att.loadSig, att.data.slot.start_beacon_time)
|
2021-04-12 20:25:09 +00:00
|
|
|
inc attestations
|
|
|
|
|
|
|
|
check:
|
Implement split preset/config support (#2710)
* Implement split preset/config support
This is the initial bulk refactor to introduce runtime config values in
a number of places, somewhat replacing the existing mechanism of loading
network metadata.
It still needs more work, this is the initial refactor that introduces
runtime configuration in some of the places that need it.
The PR changes the way presets and constants work, to match the spec. In
particular, a "preset" now refers to the compile-time configuration
while a "cfg" or "RuntimeConfig" is the dynamic part.
A single binary can support either mainnet or minimal, but not both.
Support for other presets has been removed completely (can be readded,
in case there's need).
There's a number of outstanding tasks:
* `SECONDS_PER_SLOT` still needs fixing
* loading custom runtime configs needs redoing
* checking constants against YAML file
* yeerongpilly support
`build/nimbus_beacon_node --network=yeerongpilly --discv5:no --log-level=DEBUG`
* load fork epoch from config
* fix fork digest sent in status
* nicer error string for request failures
* fix tools
* one more
* fixup
* fixup
* fixup
* use "standard" network definition folder in local testnet
Files are loaded from their standard locations, including genesis etc,
to conform to the format used in the `eth2-networks` repo.
* fix launch scripts, allow unknown config values
* fix base config of rest test
* cleanups
* bundle mainnet config using common loader
* fix spec links and names
* only include supported preset in binary
* drop yeerongpilly, add altair-devnet-0, support boot_enr.yaml
2021-07-12 13:01:38 +00:00
|
|
|
process_slots(
|
2022-03-16 07:20:40 +00:00
|
|
|
defaultRuntimeConfig, state[],
|
|
|
|
getStateField(state[], slot) + 1, cache, info, {}).isOk()
|
2021-04-12 20:25:09 +00:00
|
|
|
|
|
|
|
doAssert attestations.uint64 > MAX_ATTESTATIONS,
|
|
|
|
"6*SLOTS_PER_EPOCH validators > 128 mainnet MAX_ATTESTATIONS"
|
|
|
|
check:
|
|
|
|
# Fill block with attestations
|
2022-03-16 07:20:40 +00:00
|
|
|
pool[].getAttestationsForBlock(state[], cache).lenu64() ==
|
2021-04-12 20:25:09 +00:00
|
|
|
MAX_ATTESTATIONS
|
2021-04-16 08:49:37 +00:00
|
|
|
pool[].getAggregatedAttestation(
|
2022-03-16 07:20:40 +00:00
|
|
|
getStateField(state[], slot) - 1, 0.CommitteeIndex).isSome()
|
2021-04-12 20:25:09 +00:00
|
|
|
|
2021-04-28 16:41:02 +00:00
|
|
|
test "Attestations may arrive in any order" & preset():
|
2020-07-15 10:44:18 +00:00
|
|
|
var cache = StateCache()
|
2020-04-29 11:44:07 +00:00
|
|
|
let
|
|
|
|
# Create an attestation for slot 1!
|
|
|
|
bc0 = get_beacon_committee(
|
2022-03-16 07:20:40 +00:00
|
|
|
state[], getStateField(state[], slot), 0.CommitteeIndex, cache)
|
|
|
|
attestation0 = makeAttestation(
|
|
|
|
state[], state[].latest_block_root, bc0[0], cache)
|
2020-04-29 11:44:07 +00:00
|
|
|
|
2020-05-19 15:46:29 +00:00
|
|
|
check:
|
2021-06-11 17:51:46 +00:00
|
|
|
process_slots(
|
2022-03-16 07:20:40 +00:00
|
|
|
defaultRuntimeConfig, state[], getStateField(state[], slot) + 1,
|
2022-01-17 11:19:58 +00:00
|
|
|
cache, info, {}).isOk()
|
2020-04-29 11:44:07 +00:00
|
|
|
|
|
|
|
let
|
2022-03-16 07:20:40 +00:00
|
|
|
bc1 = get_beacon_committee(state[],
|
|
|
|
getStateField(state[], slot), 0.CommitteeIndex, cache)
|
|
|
|
attestation1 = makeAttestation(
|
|
|
|
state[], state[].latest_block_root, bc1[0], cache)
|
2020-04-29 11:44:07 +00:00
|
|
|
|
|
|
|
# test reverse order
|
2021-04-09 12:59:24 +00:00
|
|
|
pool[].addAttestation(
|
2021-12-21 18:56:08 +00:00
|
|
|
attestation1, @[bc1[0]], attestation1.loadSig,
|
2022-01-11 10:01:54 +00:00
|
|
|
attestation1.data.slot.start_beacon_time)
|
2021-04-09 12:59:24 +00:00
|
|
|
pool[].addAttestation(
|
2021-12-21 18:56:08 +00:00
|
|
|
attestation0, @[bc0[0]], attestation0.loadSig,
|
2022-01-11 10:01:54 +00:00
|
|
|
attestation0.data.slot.start_beacon_time)
|
2020-04-29 11:44:07 +00:00
|
|
|
|
2022-03-16 07:20:40 +00:00
|
|
|
let attestations = pool[].getAttestationsForBlock(state[], cache)
|
2020-04-29 11:44:07 +00:00
|
|
|
|
|
|
|
check:
|
|
|
|
attestations.len == 1
|
|
|
|
|
2021-04-28 16:41:02 +00:00
|
|
|
test "Attestations should be combined" & preset():
|
2020-07-15 10:44:18 +00:00
|
|
|
var cache = StateCache()
|
2020-04-29 11:44:07 +00:00
|
|
|
let
|
|
|
|
# Create an attestation for slot 1!
|
|
|
|
bc0 = get_beacon_committee(
|
2022-03-16 07:20:40 +00:00
|
|
|
state[], getStateField(state[], slot), 0.CommitteeIndex, cache)
|
2021-06-11 17:51:46 +00:00
|
|
|
attestation0 =
|
2022-03-16 07:20:40 +00:00
|
|
|
makeAttestation(state[], state[].latest_block_root, bc0[0], cache)
|
2021-06-11 17:51:46 +00:00
|
|
|
attestation1 =
|
2022-03-16 07:20:40 +00:00
|
|
|
makeAttestation(state[], state[].latest_block_root, bc0[1], cache)
|
2020-04-29 11:44:07 +00:00
|
|
|
|
2021-04-09 12:59:24 +00:00
|
|
|
pool[].addAttestation(
|
2021-12-21 18:56:08 +00:00
|
|
|
attestation0, @[bc0[0]], attestation0.loadSig,
|
2022-01-11 10:01:54 +00:00
|
|
|
attestation0.data.slot.start_beacon_time)
|
2021-04-09 12:59:24 +00:00
|
|
|
pool[].addAttestation(
|
2021-12-21 18:56:08 +00:00
|
|
|
attestation1, @[bc0[1]], attestation1.loadSig,
|
2022-01-11 10:01:54 +00:00
|
|
|
attestation1.data.slot.start_beacon_time)
|
2020-04-29 11:44:07 +00:00
|
|
|
|
2020-05-19 15:46:29 +00:00
|
|
|
check:
|
2021-05-07 11:36:21 +00:00
|
|
|
process_slots(
|
2022-03-16 07:20:40 +00:00
|
|
|
defaultRuntimeConfig, state[],
|
2022-01-17 11:19:58 +00:00
|
|
|
MIN_ATTESTATION_INCLUSION_DELAY.Slot + 1, cache, info, {}).isOk()
|
2020-04-29 11:44:07 +00:00
|
|
|
|
2022-03-16 07:20:40 +00:00
|
|
|
let attestations = pool[].getAttestationsForBlock(state[], cache)
|
2020-04-29 11:44:07 +00:00
|
|
|
|
|
|
|
check:
|
|
|
|
attestations.len == 1
|
|
|
|
|
2021-04-28 16:41:02 +00:00
|
|
|
test "Attestations may overlap, bigger first" & preset():
|
2020-07-15 10:44:18 +00:00
|
|
|
var cache = StateCache()
|
2020-04-29 11:44:07 +00:00
|
|
|
|
|
|
|
var
|
|
|
|
# Create an attestation for slot 1!
|
|
|
|
bc0 = get_beacon_committee(
|
2022-03-16 07:20:40 +00:00
|
|
|
state[], getStateField(state[], slot), 0.CommitteeIndex, cache)
|
|
|
|
attestation0 = makeAttestation(
|
|
|
|
state[], state[].latest_block_root, bc0[0], cache)
|
|
|
|
attestation1 = makeAttestation(
|
|
|
|
state[], state[].latest_block_root, bc0[1], cache)
|
2019-12-19 14:13:35 +00:00
|
|
|
|
2021-01-22 13:29:04 +00:00
|
|
|
attestation0.combine(attestation1)
|
2020-04-29 11:44:07 +00:00
|
|
|
|
2021-04-09 12:59:24 +00:00
|
|
|
pool[].addAttestation(
|
2021-12-21 18:56:08 +00:00
|
|
|
attestation0, @[bc0[0]], attestation0.loadSig,
|
2022-01-11 10:01:54 +00:00
|
|
|
attestation0.data.slot.start_beacon_time)
|
2021-04-09 12:59:24 +00:00
|
|
|
pool[].addAttestation(
|
2021-12-21 18:56:08 +00:00
|
|
|
attestation1, @[bc0[1]], attestation1.loadSig,
|
2022-01-11 10:01:54 +00:00
|
|
|
attestation1.data.slot.start_beacon_time)
|
2019-12-19 13:02:28 +00:00
|
|
|
|
2020-05-19 15:46:29 +00:00
|
|
|
check:
|
2021-05-07 11:36:21 +00:00
|
|
|
process_slots(
|
2022-03-16 07:20:40 +00:00
|
|
|
defaultRuntimeConfig, state[],
|
2022-01-17 11:19:58 +00:00
|
|
|
MIN_ATTESTATION_INCLUSION_DELAY.Slot + 1, cache, info, {}).isOk()
|
2019-12-19 13:02:28 +00:00
|
|
|
|
2022-03-16 07:20:40 +00:00
|
|
|
let attestations = pool[].getAttestationsForBlock(state[], cache)
|
2019-12-19 13:02:28 +00:00
|
|
|
|
2020-04-29 11:44:07 +00:00
|
|
|
check:
|
|
|
|
attestations.len == 1
|
2019-12-19 13:02:28 +00:00
|
|
|
|
2021-04-28 16:41:02 +00:00
|
|
|
test "Attestations may overlap, smaller first" & preset():
|
2020-07-15 10:44:18 +00:00
|
|
|
var cache = StateCache()
|
2020-04-29 11:44:07 +00:00
|
|
|
var
|
|
|
|
# Create an attestation for slot 1!
|
2022-03-16 07:20:40 +00:00
|
|
|
bc0 = get_beacon_committee(state[],
|
|
|
|
getStateField(state[], slot), 0.CommitteeIndex, cache)
|
|
|
|
attestation0 = makeAttestation(
|
|
|
|
state[], state[].latest_block_root, bc0[0], cache)
|
|
|
|
attestation1 = makeAttestation(
|
|
|
|
state[], state[].latest_block_root, bc0[1], cache)
|
2019-12-19 13:02:28 +00:00
|
|
|
|
2021-01-22 13:29:04 +00:00
|
|
|
attestation0.combine(attestation1)
|
2019-12-19 14:13:35 +00:00
|
|
|
|
2021-04-09 12:59:24 +00:00
|
|
|
pool[].addAttestation(
|
2021-12-21 18:56:08 +00:00
|
|
|
attestation1, @[bc0[1]], attestation1.loadSig,
|
2022-01-11 10:01:54 +00:00
|
|
|
attestation1.data.slot.start_beacon_time)
|
2021-04-09 12:59:24 +00:00
|
|
|
pool[].addAttestation(
|
2021-12-21 18:56:08 +00:00
|
|
|
attestation0, @[bc0[0]], attestation0.loadSig,
|
2022-01-11 10:01:54 +00:00
|
|
|
attestation0.data.slot.start_beacon_time)
|
2019-12-19 13:02:28 +00:00
|
|
|
|
2020-05-19 15:46:29 +00:00
|
|
|
check:
|
2021-05-07 11:36:21 +00:00
|
|
|
process_slots(
|
2022-03-16 07:20:40 +00:00
|
|
|
defaultRuntimeConfig, state[],
|
2022-01-17 11:19:58 +00:00
|
|
|
MIN_ATTESTATION_INCLUSION_DELAY.Slot + 1, cache, info, {}).isOk()
|
2019-12-19 13:02:28 +00:00
|
|
|
|
2022-03-16 07:20:40 +00:00
|
|
|
let attestations = pool[].getAttestationsForBlock(state[], cache)
|
2019-12-19 13:02:28 +00:00
|
|
|
|
2020-04-29 11:44:07 +00:00
|
|
|
check:
|
|
|
|
attestations.len == 1
|
2019-12-19 13:02:28 +00:00
|
|
|
|
2021-04-28 16:41:02 +00:00
|
|
|
test "Fork choice returns latest block with no attestations":
|
2020-07-15 10:44:18 +00:00
|
|
|
var cache = StateCache()
|
2020-04-29 11:44:07 +00:00
|
|
|
let
|
2022-03-16 07:20:40 +00:00
|
|
|
b1 = addTestBlock(state[], cache).phase0Data
|
Backfill support for ChainDAG (#3171)
In the ChainDAG, 3 block pointers are kept: genesis, tail and head. This
PR adds one more block pointer: the backfill block which represents the
block that has been backfilled so far.
When doing a checkpoint sync, a random block is given as starting point
- this is the tail block, and we require that the tail block has a
corresponding state.
When backfilling, we end up with blocks without corresponding states,
hence we cannot use `tail` as a backfill pointer - there is no state.
Nonetheless, we need to keep track of where we are in the backfill
process between restarts, such that we can answer GetBeaconBlocksByRange
requests.
This PR adds the basic support for backfill handling - it needs to be
integrated with backfill sync, and the REST API needs to be adjusted to
take advantage of the new backfilled blocks when responding to certain
requests.
Future work will also enable moving the tail in either direction:
* pruning means moving the tail forward in time and removing states
* backwards means recreating past states from genesis, such that
intermediate states are recreated step by step all the way to the tail -
at that point, tail, genesis and backfill will match up.
* backfilling is done when backfill != genesis - later, this will be the
WSS checkpoint instead
2021-12-13 13:36:06 +00:00
|
|
|
b1Add = dag.addHeadBlock(verifier, b1) do (
|
2021-08-12 13:08:20 +00:00
|
|
|
blckRef: BlockRef, signedBlock: phase0.TrustedSignedBeaconBlock,
|
2021-06-21 08:35:24 +00:00
|
|
|
epochRef: EpochRef):
|
2020-07-22 09:42:55 +00:00
|
|
|
# Callback add to fork choice if valid
|
2021-12-21 18:56:08 +00:00
|
|
|
pool[].addForkChoice(
|
2022-01-11 10:01:54 +00:00
|
|
|
epochRef, blckRef, signedBlock.message, blckRef.slot.start_beacon_time)
|
2020-07-22 09:42:55 +00:00
|
|
|
|
limit by-root requests to non-finalized blocks (#3293)
* limit by-root requests to non-finalized blocks
Presently, we keep a mapping from block root to `BlockRef` in memory -
this has simplified reasoning about the dag, but is not sustainable with
the chain growing.
We can distinguish between two cases where by-root access is useful:
* unfinalized blocks - this is where the beacon chain is operating
generally, by validating incoming data as interesting for future fork
choice decisions - bounded by the length of the unfinalized period
* finalized blocks - historical access in the REST API etc - no bounds,
really
In this PR, we limit the by-root block index to the first use case:
finalized chain data can more efficiently be addressed by slot number.
Future work includes:
* limiting the `BlockRef` horizon in general - each instance is 40
bytes+overhead which adds up - this needs further refactoring to deal
with the tail vs state problem
* persisting the finalized slot-to-hash index - this one also keeps
growing unbounded (albeit slowly)
Anyway, this PR easily shaves ~128mb of memory usage at the time of
writing.
* No longer honor `BeaconBlocksByRoot` requests outside of the
non-finalized period - previously, Nimbus would generously return any
block through this libp2p request - per the spec, finalized blocks
should be fetched via `BeaconBlocksByRange` instead.
* return `Opt[BlockRef]` instead of `nil` when blocks can't be found -
this becomes a lot more common now and thus deserves more attention
* `dag.blocks` -> `dag.forkBlocks` - this index only carries unfinalized
blocks from now - `finalizedBlocks` covers the other `BlockRef`
instances
* in backfill, verify that the last backfilled block leads back to
genesis, or panic
* add backfill timings to log
* fix missing check that `BlockRef` block can be fetched with
`getForkedBlock` reliably
* shortcut doppelganger check when feature is not enabled
* in REST/JSON-RPC, fetch blocks without involving `BlockRef`
* fix dag.blocks ref
2022-01-21 11:33:16 +00:00
|
|
|
let head = pool[].selectHead(b1Add[].slot.start_beacon_time).get()
|
2020-04-29 11:44:07 +00:00
|
|
|
check:
|
2020-07-09 09:29:32 +00:00
|
|
|
head == b1Add[]
|
2019-12-19 14:13:35 +00:00
|
|
|
|
2020-04-29 11:44:07 +00:00
|
|
|
let
|
2022-03-16 07:20:40 +00:00
|
|
|
b2 = addTestBlock(state[], cache).phase0Data
|
Backfill support for ChainDAG (#3171)
In the ChainDAG, 3 block pointers are kept: genesis, tail and head. This
PR adds one more block pointer: the backfill block which represents the
block that has been backfilled so far.
When doing a checkpoint sync, a random block is given as starting point
- this is the tail block, and we require that the tail block has a
corresponding state.
When backfilling, we end up with blocks without corresponding states,
hence we cannot use `tail` as a backfill pointer - there is no state.
Nonetheless, we need to keep track of where we are in the backfill
process between restarts, such that we can answer GetBeaconBlocksByRange
requests.
This PR adds the basic support for backfill handling - it needs to be
integrated with backfill sync, and the REST API needs to be adjusted to
take advantage of the new backfilled blocks when responding to certain
requests.
Future work will also enable moving the tail in either direction:
* pruning means moving the tail forward in time and removing states
* backwards means recreating past states from genesis, such that
intermediate states are recreated step by step all the way to the tail -
at that point, tail, genesis and backfill will match up.
* backfilling is done when backfill != genesis - later, this will be the
WSS checkpoint instead
2021-12-13 13:36:06 +00:00
|
|
|
b2Add = dag.addHeadBlock(verifier, b2) do (
|
2021-08-12 13:08:20 +00:00
|
|
|
blckRef: BlockRef, signedBlock: phase0.TrustedSignedBeaconBlock,
|
2021-06-21 08:35:24 +00:00
|
|
|
epochRef: EpochRef):
|
2020-07-22 09:42:55 +00:00
|
|
|
# Callback add to fork choice if valid
|
2021-12-21 18:56:08 +00:00
|
|
|
pool[].addForkChoice(
|
2022-01-11 10:01:54 +00:00
|
|
|
epochRef, blckRef, signedBlock.message, blckRef.slot.start_beacon_time)
|
2020-06-10 06:58:12 +00:00
|
|
|
|
limit by-root requests to non-finalized blocks (#3293)
* limit by-root requests to non-finalized blocks
Presently, we keep a mapping from block root to `BlockRef` in memory -
this has simplified reasoning about the dag, but is not sustainable with
the chain growing.
We can distinguish between two cases where by-root access is useful:
* unfinalized blocks - this is where the beacon chain is operating
generally, by validating incoming data as interesting for future fork
choice decisions - bounded by the length of the unfinalized period
* finalized blocks - historical access in the REST API etc - no bounds,
really
In this PR, we limit the by-root block index to the first use case:
finalized chain data can more efficiently be addressed by slot number.
Future work includes:
* limiting the `BlockRef` horizon in general - each instance is 40
bytes+overhead which adds up - this needs further refactoring to deal
with the tail vs state problem
* persisting the finalized slot-to-hash index - this one also keeps
growing unbounded (albeit slowly)
Anyway, this PR easily shaves ~128mb of memory usage at the time of
writing.
* No longer honor `BeaconBlocksByRoot` requests outside of the
non-finalized period - previously, Nimbus would generously return any
block through this libp2p request - per the spec, finalized blocks
should be fetched via `BeaconBlocksByRange` instead.
* return `Opt[BlockRef]` instead of `nil` when blocks can't be found -
this becomes a lot more common now and thus deserves more attention
* `dag.blocks` -> `dag.forkBlocks` - this index only carries unfinalized
blocks from now - `finalizedBlocks` covers the other `BlockRef`
instances
* in backfill, verify that the last backfilled block leads back to
genesis, or panic
* add backfill timings to log
* fix missing check that `BlockRef` block can be fetched with
`getForkedBlock` reliably
* shortcut doppelganger check when feature is not enabled
* in REST/JSON-RPC, fetch blocks without involving `BlockRef`
* fix dag.blocks ref
2022-01-21 11:33:16 +00:00
|
|
|
let head2 = pool[].selectHead(b2Add[].slot.start_beacon_time).get()
|
2019-12-19 13:02:28 +00:00
|
|
|
|
2020-04-29 11:44:07 +00:00
|
|
|
check:
|
2020-07-09 09:29:32 +00:00
|
|
|
head2 == b2Add[]
|
2019-12-19 13:02:28 +00:00
|
|
|
|
2021-04-28 16:41:02 +00:00
|
|
|
test "Fork choice returns block with attestation":
|
2020-07-15 10:44:18 +00:00
|
|
|
var cache = StateCache()
|
2020-04-29 11:44:07 +00:00
|
|
|
let
|
2022-03-16 07:20:40 +00:00
|
|
|
b10 = makeTestBlock(state[], cache).phase0Data
|
Backfill support for ChainDAG (#3171)
In the ChainDAG, 3 block pointers are kept: genesis, tail and head. This
PR adds one more block pointer: the backfill block which represents the
block that has been backfilled so far.
When doing a checkpoint sync, a random block is given as starting point
- this is the tail block, and we require that the tail block has a
corresponding state.
When backfilling, we end up with blocks without corresponding states,
hence we cannot use `tail` as a backfill pointer - there is no state.
Nonetheless, we need to keep track of where we are in the backfill
process between restarts, such that we can answer GetBeaconBlocksByRange
requests.
This PR adds the basic support for backfill handling - it needs to be
integrated with backfill sync, and the REST API needs to be adjusted to
take advantage of the new backfilled blocks when responding to certain
requests.
Future work will also enable moving the tail in either direction:
* pruning means moving the tail forward in time and removing states
* backwards means recreating past states from genesis, such that
intermediate states are recreated step by step all the way to the tail -
at that point, tail, genesis and backfill will match up.
* backfilling is done when backfill != genesis - later, this will be the
WSS checkpoint instead
2021-12-13 13:36:06 +00:00
|
|
|
b10Add = dag.addHeadBlock(verifier, b10) do (
|
2021-08-12 13:08:20 +00:00
|
|
|
blckRef: BlockRef, signedBlock: phase0.TrustedSignedBeaconBlock,
|
2021-06-21 08:35:24 +00:00
|
|
|
epochRef: EpochRef):
|
2020-07-22 09:42:55 +00:00
|
|
|
# Callback add to fork choice if valid
|
2021-12-21 18:56:08 +00:00
|
|
|
pool[].addForkChoice(
|
2022-01-11 10:01:54 +00:00
|
|
|
epochRef, blckRef, signedBlock.message, blckRef.slot.start_beacon_time)
|
2020-06-10 06:58:12 +00:00
|
|
|
|
limit by-root requests to non-finalized blocks (#3293)
* limit by-root requests to non-finalized blocks
Presently, we keep a mapping from block root to `BlockRef` in memory -
this has simplified reasoning about the dag, but is not sustainable with
the chain growing.
We can distinguish between two cases where by-root access is useful:
* unfinalized blocks - this is where the beacon chain is operating
generally, by validating incoming data as interesting for future fork
choice decisions - bounded by the length of the unfinalized period
* finalized blocks - historical access in the REST API etc - no bounds,
really
In this PR, we limit the by-root block index to the first use case:
finalized chain data can more efficiently be addressed by slot number.
Future work includes:
* limiting the `BlockRef` horizon in general - each instance is 40
bytes+overhead which adds up - this needs further refactoring to deal
with the tail vs state problem
* persisting the finalized slot-to-hash index - this one also keeps
growing unbounded (albeit slowly)
Anyway, this PR easily shaves ~128mb of memory usage at the time of
writing.
* No longer honor `BeaconBlocksByRoot` requests outside of the
non-finalized period - previously, Nimbus would generously return any
block through this libp2p request - per the spec, finalized blocks
should be fetched via `BeaconBlocksByRange` instead.
* return `Opt[BlockRef]` instead of `nil` when blocks can't be found -
this becomes a lot more common now and thus deserves more attention
* `dag.blocks` -> `dag.forkBlocks` - this index only carries unfinalized
blocks from now - `finalizedBlocks` covers the other `BlockRef`
instances
* in backfill, verify that the last backfilled block leads back to
genesis, or panic
* add backfill timings to log
* fix missing check that `BlockRef` block can be fetched with
`getForkedBlock` reliably
* shortcut doppelganger check when feature is not enabled
* in REST/JSON-RPC, fetch blocks without involving `BlockRef`
* fix dag.blocks ref
2022-01-21 11:33:16 +00:00
|
|
|
let head = pool[].selectHead(b10Add[].slot.start_beacon_time).get()
|
2019-12-19 13:02:28 +00:00
|
|
|
|
2020-04-29 11:44:07 +00:00
|
|
|
check:
|
2020-07-09 09:29:32 +00:00
|
|
|
head == b10Add[]
|
2019-12-19 13:02:28 +00:00
|
|
|
|
2022-04-12 10:06:30 +00:00
|
|
|
# Add a block too late to be timely enough to be proposer-boosted, which
|
|
|
|
# would otherwise cause it to be selected as head
|
2020-04-29 11:44:07 +00:00
|
|
|
let
|
2022-03-16 07:20:40 +00:00
|
|
|
b11 = makeTestBlock(state[], cache,
|
2020-06-29 17:30:19 +00:00
|
|
|
graffiti = GraffitiBytes [1'u8, 0, 0, 0 ,0 ,0 ,0 ,0 ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
2021-10-18 16:37:27 +00:00
|
|
|
).phase0Data
|
Backfill support for ChainDAG (#3171)
In the ChainDAG, 3 block pointers are kept: genesis, tail and head. This
PR adds one more block pointer: the backfill block which represents the
block that has been backfilled so far.
When doing a checkpoint sync, a random block is given as starting point
- this is the tail block, and we require that the tail block has a
corresponding state.
When backfilling, we end up with blocks without corresponding states,
hence we cannot use `tail` as a backfill pointer - there is no state.
Nonetheless, we need to keep track of where we are in the backfill
process between restarts, such that we can answer GetBeaconBlocksByRange
requests.
This PR adds the basic support for backfill handling - it needs to be
integrated with backfill sync, and the REST API needs to be adjusted to
take advantage of the new backfilled blocks when responding to certain
requests.
Future work will also enable moving the tail in either direction:
* pruning means moving the tail forward in time and removing states
* backwards means recreating past states from genesis, such that
intermediate states are recreated step by step all the way to the tail -
at that point, tail, genesis and backfill will match up.
* backfilling is done when backfill != genesis - later, this will be the
WSS checkpoint instead
2021-12-13 13:36:06 +00:00
|
|
|
b11Add = dag.addHeadBlock(verifier, b11) do (
|
2021-08-12 13:08:20 +00:00
|
|
|
blckRef: BlockRef, signedBlock: phase0.TrustedSignedBeaconBlock,
|
2021-06-21 08:35:24 +00:00
|
|
|
epochRef: EpochRef):
|
2020-07-22 09:42:55 +00:00
|
|
|
# Callback add to fork choice if valid
|
2021-12-21 18:56:08 +00:00
|
|
|
pool[].addForkChoice(
|
2022-04-12 10:06:30 +00:00
|
|
|
epochRef, blckRef, signedBlock.message,
|
|
|
|
blckRef.slot.start_beacon_time + SECONDS_PER_SLOT.int64.seconds)
|
2019-12-19 13:02:28 +00:00
|
|
|
|
2020-04-29 11:44:07 +00:00
|
|
|
bc1 = get_beacon_committee(
|
2022-03-16 07:20:40 +00:00
|
|
|
state[], getStateField(state[], slot) - 1, 1.CommitteeIndex,
|
2021-06-11 17:51:46 +00:00
|
|
|
cache)
|
2022-03-16 07:20:40 +00:00
|
|
|
attestation0 = makeAttestation(state[], b10.root, bc1[0], cache)
|
2019-06-03 08:26:38 +00:00
|
|
|
|
2021-04-09 12:59:24 +00:00
|
|
|
pool[].addAttestation(
|
2021-12-21 18:56:08 +00:00
|
|
|
attestation0, @[bc1[0]], attestation0.loadSig,
|
2022-01-11 10:01:54 +00:00
|
|
|
attestation0.data.slot.start_beacon_time)
|
2019-06-03 08:26:38 +00:00
|
|
|
|
limit by-root requests to non-finalized blocks (#3293)
* limit by-root requests to non-finalized blocks
Presently, we keep a mapping from block root to `BlockRef` in memory -
this has simplified reasoning about the dag, but is not sustainable with
the chain growing.
We can distinguish between two cases where by-root access is useful:
* unfinalized blocks - this is where the beacon chain is operating
generally, by validating incoming data as interesting for future fork
choice decisions - bounded by the length of the unfinalized period
* finalized blocks - historical access in the REST API etc - no bounds,
really
In this PR, we limit the by-root block index to the first use case:
finalized chain data can more efficiently be addressed by slot number.
Future work includes:
* limiting the `BlockRef` horizon in general - each instance is 40
bytes+overhead which adds up - this needs further refactoring to deal
with the tail vs state problem
* persisting the finalized slot-to-hash index - this one also keeps
growing unbounded (albeit slowly)
Anyway, this PR easily shaves ~128mb of memory usage at the time of
writing.
* No longer honor `BeaconBlocksByRoot` requests outside of the
non-finalized period - previously, Nimbus would generously return any
block through this libp2p request - per the spec, finalized blocks
should be fetched via `BeaconBlocksByRange` instead.
* return `Opt[BlockRef]` instead of `nil` when blocks can't be found -
this becomes a lot more common now and thus deserves more attention
* `dag.blocks` -> `dag.forkBlocks` - this index only carries unfinalized
blocks from now - `finalizedBlocks` covers the other `BlockRef`
instances
* in backfill, verify that the last backfilled block leads back to
genesis, or panic
* add backfill timings to log
* fix missing check that `BlockRef` block can be fetched with
`getForkedBlock` reliably
* shortcut doppelganger check when feature is not enabled
* in REST/JSON-RPC, fetch blocks without involving `BlockRef`
* fix dag.blocks ref
2022-01-21 11:33:16 +00:00
|
|
|
let head2 = pool[].selectHead(b10Add[].slot.start_beacon_time).get()
|
2019-06-03 08:26:38 +00:00
|
|
|
|
2020-04-29 11:44:07 +00:00
|
|
|
check:
|
|
|
|
# Single vote for b10 and no votes for b11
|
2020-07-09 09:29:32 +00:00
|
|
|
head2 == b10Add[]
|
2019-06-03 08:26:38 +00:00
|
|
|
|
2020-04-29 11:44:07 +00:00
|
|
|
let
|
2022-03-16 07:20:40 +00:00
|
|
|
attestation1 = makeAttestation(state[], b11.root, bc1[1], cache)
|
|
|
|
attestation2 = makeAttestation(state[], b11.root, bc1[2], cache)
|
2021-04-09 12:59:24 +00:00
|
|
|
pool[].addAttestation(
|
2021-12-21 18:56:08 +00:00
|
|
|
attestation1, @[bc1[1]], attestation1.loadSig,
|
2022-01-11 10:01:54 +00:00
|
|
|
attestation1.data.slot.start_beacon_time)
|
2019-06-03 08:26:38 +00:00
|
|
|
|
limit by-root requests to non-finalized blocks (#3293)
* limit by-root requests to non-finalized blocks
Presently, we keep a mapping from block root to `BlockRef` in memory -
this has simplified reasoning about the dag, but is not sustainable with
the chain growing.
We can distinguish between two cases where by-root access is useful:
* unfinalized blocks - this is where the beacon chain is operating
generally, by validating incoming data as interesting for future fork
choice decisions - bounded by the length of the unfinalized period
* finalized blocks - historical access in the REST API etc - no bounds,
really
In this PR, we limit the by-root block index to the first use case:
finalized chain data can more efficiently be addressed by slot number.
Future work includes:
* limiting the `BlockRef` horizon in general - each instance is 40
bytes+overhead which adds up - this needs further refactoring to deal
with the tail vs state problem
* persisting the finalized slot-to-hash index - this one also keeps
growing unbounded (albeit slowly)
Anyway, this PR easily shaves ~128mb of memory usage at the time of
writing.
* No longer honor `BeaconBlocksByRoot` requests outside of the
non-finalized period - previously, Nimbus would generously return any
block through this libp2p request - per the spec, finalized blocks
should be fetched via `BeaconBlocksByRange` instead.
* return `Opt[BlockRef]` instead of `nil` when blocks can't be found -
this becomes a lot more common now and thus deserves more attention
* `dag.blocks` -> `dag.forkBlocks` - this index only carries unfinalized
blocks from now - `finalizedBlocks` covers the other `BlockRef`
instances
* in backfill, verify that the last backfilled block leads back to
genesis, or panic
* add backfill timings to log
* fix missing check that `BlockRef` block can be fetched with
`getForkedBlock` reliably
* shortcut doppelganger check when feature is not enabled
* in REST/JSON-RPC, fetch blocks without involving `BlockRef`
* fix dag.blocks ref
2022-01-21 11:33:16 +00:00
|
|
|
let head3 = pool[].selectHead(b10Add[].slot.start_beacon_time).get()
|
2020-07-25 19:41:12 +00:00
|
|
|
let bigger = if b11.root.data < b10.root.data: b10Add else: b11Add
|
2020-04-29 11:44:07 +00:00
|
|
|
|
|
|
|
check:
|
2020-06-10 06:58:12 +00:00
|
|
|
# Ties broken lexicographically in spec -> ?
|
2020-07-25 19:41:12 +00:00
|
|
|
head3 == bigger[]
|
2020-04-29 11:44:07 +00:00
|
|
|
|
2021-04-09 12:59:24 +00:00
|
|
|
pool[].addAttestation(
|
2021-12-21 18:56:08 +00:00
|
|
|
attestation2, @[bc1[2]], attestation2.loadSig,
|
2022-01-11 10:01:54 +00:00
|
|
|
attestation2.data.slot.start_beacon_time)
|
2020-04-29 11:44:07 +00:00
|
|
|
|
limit by-root requests to non-finalized blocks (#3293)
* limit by-root requests to non-finalized blocks
Presently, we keep a mapping from block root to `BlockRef` in memory -
this has simplified reasoning about the dag, but is not sustainable with
the chain growing.
We can distinguish between two cases where by-root access is useful:
* unfinalized blocks - this is where the beacon chain is operating
generally, by validating incoming data as interesting for future fork
choice decisions - bounded by the length of the unfinalized period
* finalized blocks - historical access in the REST API etc - no bounds,
really
In this PR, we limit the by-root block index to the first use case:
finalized chain data can more efficiently be addressed by slot number.
Future work includes:
* limiting the `BlockRef` horizon in general - each instance is 40
bytes+overhead which adds up - this needs further refactoring to deal
with the tail vs state problem
* persisting the finalized slot-to-hash index - this one also keeps
growing unbounded (albeit slowly)
Anyway, this PR easily shaves ~128mb of memory usage at the time of
writing.
* No longer honor `BeaconBlocksByRoot` requests outside of the
non-finalized period - previously, Nimbus would generously return any
block through this libp2p request - per the spec, finalized blocks
should be fetched via `BeaconBlocksByRange` instead.
* return `Opt[BlockRef]` instead of `nil` when blocks can't be found -
this becomes a lot more common now and thus deserves more attention
* `dag.blocks` -> `dag.forkBlocks` - this index only carries unfinalized
blocks from now - `finalizedBlocks` covers the other `BlockRef`
instances
* in backfill, verify that the last backfilled block leads back to
genesis, or panic
* add backfill timings to log
* fix missing check that `BlockRef` block can be fetched with
`getForkedBlock` reliably
* shortcut doppelganger check when feature is not enabled
* in REST/JSON-RPC, fetch blocks without involving `BlockRef`
* fix dag.blocks ref
2022-01-21 11:33:16 +00:00
|
|
|
let head4 = pool[].selectHead(b11Add[].slot.start_beacon_time).get()
|
2020-04-29 11:44:07 +00:00
|
|
|
|
|
|
|
check:
|
|
|
|
# Two votes for b11
|
2020-07-09 09:29:32 +00:00
|
|
|
head4 == b11Add[]
|
|
|
|
|
2021-04-28 16:41:02 +00:00
|
|
|
test "Trying to add a block twice tags the second as an error":
|
2020-07-15 10:44:18 +00:00
|
|
|
var cache = StateCache()
|
2020-07-09 09:29:32 +00:00
|
|
|
let
|
2022-03-16 07:20:40 +00:00
|
|
|
b10 = makeTestBlock(state[], cache).phase0Data
|
Backfill support for ChainDAG (#3171)
In the ChainDAG, 3 block pointers are kept: genesis, tail and head. This
PR adds one more block pointer: the backfill block which represents the
block that has been backfilled so far.
When doing a checkpoint sync, a random block is given as starting point
- this is the tail block, and we require that the tail block has a
corresponding state.
When backfilling, we end up with blocks without corresponding states,
hence we cannot use `tail` as a backfill pointer - there is no state.
Nonetheless, we need to keep track of where we are in the backfill
process between restarts, such that we can answer GetBeaconBlocksByRange
requests.
This PR adds the basic support for backfill handling - it needs to be
integrated with backfill sync, and the REST API needs to be adjusted to
take advantage of the new backfilled blocks when responding to certain
requests.
Future work will also enable moving the tail in either direction:
* pruning means moving the tail forward in time and removing states
* backwards means recreating past states from genesis, such that
intermediate states are recreated step by step all the way to the tail -
at that point, tail, genesis and backfill will match up.
* backfilling is done when backfill != genesis - later, this will be the
WSS checkpoint instead
2021-12-13 13:36:06 +00:00
|
|
|
b10Add = dag.addHeadBlock(verifier, b10) do (
|
2021-08-12 13:08:20 +00:00
|
|
|
blckRef: BlockRef, signedBlock: phase0.TrustedSignedBeaconBlock,
|
2021-06-21 08:35:24 +00:00
|
|
|
epochRef: EpochRef):
|
2020-07-22 09:42:55 +00:00
|
|
|
# Callback add to fork choice if valid
|
2021-12-21 18:56:08 +00:00
|
|
|
pool[].addForkChoice(epochRef, blckRef, signedBlock.message,
|
2022-01-11 10:01:54 +00:00
|
|
|
blckRef.slot.start_beacon_time)
|
2020-07-09 09:29:32 +00:00
|
|
|
|
limit by-root requests to non-finalized blocks (#3293)
* limit by-root requests to non-finalized blocks
Presently, we keep a mapping from block root to `BlockRef` in memory -
this has simplified reasoning about the dag, but is not sustainable with
the chain growing.
We can distinguish between two cases where by-root access is useful:
* unfinalized blocks - this is where the beacon chain is operating
generally, by validating incoming data as interesting for future fork
choice decisions - bounded by the length of the unfinalized period
* finalized blocks - historical access in the REST API etc - no bounds,
really
In this PR, we limit the by-root block index to the first use case:
finalized chain data can more efficiently be addressed by slot number.
Future work includes:
* limiting the `BlockRef` horizon in general - each instance is 40
bytes+overhead which adds up - this needs further refactoring to deal
with the tail vs state problem
* persisting the finalized slot-to-hash index - this one also keeps
growing unbounded (albeit slowly)
Anyway, this PR easily shaves ~128mb of memory usage at the time of
writing.
* No longer honor `BeaconBlocksByRoot` requests outside of the
non-finalized period - previously, Nimbus would generously return any
block through this libp2p request - per the spec, finalized blocks
should be fetched via `BeaconBlocksByRange` instead.
* return `Opt[BlockRef]` instead of `nil` when blocks can't be found -
this becomes a lot more common now and thus deserves more attention
* `dag.blocks` -> `dag.forkBlocks` - this index only carries unfinalized
blocks from now - `finalizedBlocks` covers the other `BlockRef`
instances
* in backfill, verify that the last backfilled block leads back to
genesis, or panic
* add backfill timings to log
* fix missing check that `BlockRef` block can be fetched with
`getForkedBlock` reliably
* shortcut doppelganger check when feature is not enabled
* in REST/JSON-RPC, fetch blocks without involving `BlockRef`
* fix dag.blocks ref
2022-01-21 11:33:16 +00:00
|
|
|
let head = pool[].selectHead(b10Add[].slot.start_beacon_time).get()
|
2020-07-09 09:29:32 +00:00
|
|
|
|
|
|
|
check:
|
|
|
|
head == b10Add[]
|
|
|
|
|
|
|
|
# -------------------------------------------------------------
|
|
|
|
# Add back the old block to ensure we have a duplicate error
|
|
|
|
let b10_clone = b10 # Assumes deep copy
|
Backfill support for ChainDAG (#3171)
In the ChainDAG, 3 block pointers are kept: genesis, tail and head. This
PR adds one more block pointer: the backfill block which represents the
block that has been backfilled so far.
When doing a checkpoint sync, a random block is given as starting point
- this is the tail block, and we require that the tail block has a
corresponding state.
When backfilling, we end up with blocks without corresponding states,
hence we cannot use `tail` as a backfill pointer - there is no state.
Nonetheless, we need to keep track of where we are in the backfill
process between restarts, such that we can answer GetBeaconBlocksByRange
requests.
This PR adds the basic support for backfill handling - it needs to be
integrated with backfill sync, and the REST API needs to be adjusted to
take advantage of the new backfilled blocks when responding to certain
requests.
Future work will also enable moving the tail in either direction:
* pruning means moving the tail forward in time and removing states
* backwards means recreating past states from genesis, such that
intermediate states are recreated step by step all the way to the tail -
at that point, tail, genesis and backfill will match up.
* backfilling is done when backfill != genesis - later, this will be the
WSS checkpoint instead
2021-12-13 13:36:06 +00:00
|
|
|
let b10Add_clone = dag.addHeadBlock(verifier, b10_clone) do (
|
2021-08-12 13:08:20 +00:00
|
|
|
blckRef: BlockRef, signedBlock: phase0.TrustedSignedBeaconBlock,
|
2021-06-21 08:35:24 +00:00
|
|
|
epochRef: EpochRef):
|
2020-07-22 09:42:55 +00:00
|
|
|
# Callback add to fork choice if valid
|
2021-12-21 18:56:08 +00:00
|
|
|
pool[].addForkChoice(
|
2022-01-11 10:01:54 +00:00
|
|
|
epochRef, blckRef, signedBlock.message, blckRef.slot.start_beacon_time)
|
2020-07-22 09:42:55 +00:00
|
|
|
|
2021-12-06 09:49:01 +00:00
|
|
|
doAssert: b10Add_clone.error == BlockError.Duplicate
|
2020-07-09 09:29:32 +00:00
|
|
|
|
2021-04-28 16:41:02 +00:00
|
|
|
test "Trying to add a duplicate block from an old pruned epoch is tagged as an error":
|
2020-08-26 15:23:34 +00:00
|
|
|
# Note: very sensitive to stack usage
|
|
|
|
|
2021-06-01 11:13:40 +00:00
|
|
|
dag.updateFlags.incl {skipBLSValidation}
|
2020-07-23 17:01:07 +00:00
|
|
|
var cache = StateCache()
|
2020-07-09 09:29:32 +00:00
|
|
|
let
|
2022-03-16 07:20:40 +00:00
|
|
|
b10 = addTestBlock(state[], cache).phase0Data
|
Backfill support for ChainDAG (#3171)
In the ChainDAG, 3 block pointers are kept: genesis, tail and head. This
PR adds one more block pointer: the backfill block which represents the
block that has been backfilled so far.
When doing a checkpoint sync, a random block is given as starting point
- this is the tail block, and we require that the tail block has a
corresponding state.
When backfilling, we end up with blocks without corresponding states,
hence we cannot use `tail` as a backfill pointer - there is no state.
Nonetheless, we need to keep track of where we are in the backfill
process between restarts, such that we can answer GetBeaconBlocksByRange
requests.
This PR adds the basic support for backfill handling - it needs to be
integrated with backfill sync, and the REST API needs to be adjusted to
take advantage of the new backfilled blocks when responding to certain
requests.
Future work will also enable moving the tail in either direction:
* pruning means moving the tail forward in time and removing states
* backwards means recreating past states from genesis, such that
intermediate states are recreated step by step all the way to the tail -
at that point, tail, genesis and backfill will match up.
* backfilling is done when backfill != genesis - later, this will be the
WSS checkpoint instead
2021-12-13 13:36:06 +00:00
|
|
|
b10Add = dag.addHeadBlock(verifier, b10) do (
|
2021-08-12 13:08:20 +00:00
|
|
|
blckRef: BlockRef, signedBlock: phase0.TrustedSignedBeaconBlock,
|
2021-06-21 08:35:24 +00:00
|
|
|
epochRef: EpochRef):
|
2020-07-22 09:42:55 +00:00
|
|
|
# Callback add to fork choice if valid
|
2021-12-21 18:56:08 +00:00
|
|
|
pool[].addForkChoice(
|
2022-01-11 10:01:54 +00:00
|
|
|
epochRef, blckRef, signedBlock.message, blckRef.slot.start_beacon_time)
|
2020-07-09 09:29:32 +00:00
|
|
|
|
limit by-root requests to non-finalized blocks (#3293)
* limit by-root requests to non-finalized blocks
Presently, we keep a mapping from block root to `BlockRef` in memory -
this has simplified reasoning about the dag, but is not sustainable with
the chain growing.
We can distinguish between two cases where by-root access is useful:
* unfinalized blocks - this is where the beacon chain is operating
generally, by validating incoming data as interesting for future fork
choice decisions - bounded by the length of the unfinalized period
* finalized blocks - historical access in the REST API etc - no bounds,
really
In this PR, we limit the by-root block index to the first use case:
finalized chain data can more efficiently be addressed by slot number.
Future work includes:
* limiting the `BlockRef` horizon in general - each instance is 40
bytes+overhead which adds up - this needs further refactoring to deal
with the tail vs state problem
* persisting the finalized slot-to-hash index - this one also keeps
growing unbounded (albeit slowly)
Anyway, this PR easily shaves ~128mb of memory usage at the time of
writing.
* No longer honor `BeaconBlocksByRoot` requests outside of the
non-finalized period - previously, Nimbus would generously return any
block through this libp2p request - per the spec, finalized blocks
should be fetched via `BeaconBlocksByRange` instead.
* return `Opt[BlockRef]` instead of `nil` when blocks can't be found -
this becomes a lot more common now and thus deserves more attention
* `dag.blocks` -> `dag.forkBlocks` - this index only carries unfinalized
blocks from now - `finalizedBlocks` covers the other `BlockRef`
instances
* in backfill, verify that the last backfilled block leads back to
genesis, or panic
* add backfill timings to log
* fix missing check that `BlockRef` block can be fetched with
`getForkedBlock` reliably
* shortcut doppelganger check when feature is not enabled
* in REST/JSON-RPC, fetch blocks without involving `BlockRef`
* fix dag.blocks ref
2022-01-21 11:33:16 +00:00
|
|
|
let head = pool[].selectHead(b10Add[].slot.start_beacon_time).get()
|
2020-07-09 09:29:32 +00:00
|
|
|
|
|
|
|
doAssert: head == b10Add[]
|
|
|
|
|
|
|
|
# -------------------------------------------------------------
|
|
|
|
let b10_clone = b10 # Assumes deep copy
|
|
|
|
|
|
|
|
# -------------------------------------------------------------
|
|
|
|
# Pass an epoch
|
|
|
|
var attestations: seq[Attestation]
|
|
|
|
|
|
|
|
for epoch in 0 ..< 5:
|
2022-01-11 10:01:54 +00:00
|
|
|
let start_slot = start_slot(Epoch epoch)
|
2020-07-25 19:41:12 +00:00
|
|
|
let committees_per_slot =
|
2022-03-16 07:20:40 +00:00
|
|
|
get_committee_count_per_slot(state[], Epoch epoch, cache)
|
2020-07-09 09:29:32 +00:00
|
|
|
for slot in start_slot ..< start_slot + SLOTS_PER_EPOCH:
|
2020-08-27 07:34:12 +00:00
|
|
|
let new_block = addTestBlock(
|
2022-03-16 07:20:40 +00:00
|
|
|
state[], cache, attestations = attestations).phase0Data
|
2020-07-09 09:29:32 +00:00
|
|
|
|
Backfill support for ChainDAG (#3171)
In the ChainDAG, 3 block pointers are kept: genesis, tail and head. This
PR adds one more block pointer: the backfill block which represents the
block that has been backfilled so far.
When doing a checkpoint sync, a random block is given as starting point
- this is the tail block, and we require that the tail block has a
corresponding state.
When backfilling, we end up with blocks without corresponding states,
hence we cannot use `tail` as a backfill pointer - there is no state.
Nonetheless, we need to keep track of where we are in the backfill
process between restarts, such that we can answer GetBeaconBlocksByRange
requests.
This PR adds the basic support for backfill handling - it needs to be
integrated with backfill sync, and the REST API needs to be adjusted to
take advantage of the new backfilled blocks when responding to certain
requests.
Future work will also enable moving the tail in either direction:
* pruning means moving the tail forward in time and removing states
* backwards means recreating past states from genesis, such that
intermediate states are recreated step by step all the way to the tail -
at that point, tail, genesis and backfill will match up.
* backfilling is done when backfill != genesis - later, this will be the
WSS checkpoint instead
2021-12-13 13:36:06 +00:00
|
|
|
let blockRef = dag.addHeadBlock(verifier, new_block) do (
|
2021-08-12 13:08:20 +00:00
|
|
|
blckRef: BlockRef, signedBlock: phase0.TrustedSignedBeaconBlock,
|
2021-06-21 08:35:24 +00:00
|
|
|
epochRef: EpochRef):
|
2020-07-22 09:42:55 +00:00
|
|
|
# Callback add to fork choice if valid
|
2021-12-21 18:56:08 +00:00
|
|
|
pool[].addForkChoice(
|
2022-01-11 10:01:54 +00:00
|
|
|
epochRef, blckRef, signedBlock.message, blckRef.slot.start_beacon_time)
|
2020-07-09 09:29:32 +00:00
|
|
|
|
limit by-root requests to non-finalized blocks (#3293)
* limit by-root requests to non-finalized blocks
Presently, we keep a mapping from block root to `BlockRef` in memory -
this has simplified reasoning about the dag, but is not sustainable with
the chain growing.
We can distinguish between two cases where by-root access is useful:
* unfinalized blocks - this is where the beacon chain is operating
generally, by validating incoming data as interesting for future fork
choice decisions - bounded by the length of the unfinalized period
* finalized blocks - historical access in the REST API etc - no bounds,
really
In this PR, we limit the by-root block index to the first use case:
finalized chain data can more efficiently be addressed by slot number.
Future work includes:
* limiting the `BlockRef` horizon in general - each instance is 40
bytes+overhead which adds up - this needs further refactoring to deal
with the tail vs state problem
* persisting the finalized slot-to-hash index - this one also keeps
growing unbounded (albeit slowly)
Anyway, this PR easily shaves ~128mb of memory usage at the time of
writing.
* No longer honor `BeaconBlocksByRoot` requests outside of the
non-finalized period - previously, Nimbus would generously return any
block through this libp2p request - per the spec, finalized blocks
should be fetched via `BeaconBlocksByRange` instead.
* return `Opt[BlockRef]` instead of `nil` when blocks can't be found -
this becomes a lot more common now and thus deserves more attention
* `dag.blocks` -> `dag.forkBlocks` - this index only carries unfinalized
blocks from now - `finalizedBlocks` covers the other `BlockRef`
instances
* in backfill, verify that the last backfilled block leads back to
genesis, or panic
* add backfill timings to log
* fix missing check that `BlockRef` block can be fetched with
`getForkedBlock` reliably
* shortcut doppelganger check when feature is not enabled
* in REST/JSON-RPC, fetch blocks without involving `BlockRef`
* fix dag.blocks ref
2022-01-21 11:33:16 +00:00
|
|
|
let head = pool[].selectHead(blockRef[].slot.start_beacon_time).get()
|
2021-04-12 20:25:09 +00:00
|
|
|
doAssert: head == blockRef[]
|
2021-12-06 09:49:01 +00:00
|
|
|
dag.updateHead(head, quarantine[])
|
2021-06-01 11:13:40 +00:00
|
|
|
pruneAtFinalization(dag, pool[])
|
2020-07-09 09:29:32 +00:00
|
|
|
|
|
|
|
attestations.setlen(0)
|
2022-01-08 23:28:49 +00:00
|
|
|
for committee_index in get_committee_indices(committees_per_slot):
|
2020-07-09 09:29:32 +00:00
|
|
|
let committee = get_beacon_committee(
|
2022-03-16 07:20:40 +00:00
|
|
|
state[], getStateField(state[], slot), committee_index,
|
2021-04-16 08:49:37 +00:00
|
|
|
cache)
|
2020-07-09 09:29:32 +00:00
|
|
|
|
|
|
|
# Create a bitfield filled with the given count per attestation,
|
|
|
|
# exactly on the right-most part of the committee field.
|
|
|
|
var aggregation_bits = init(CommitteeValidatorsBits, committee.len)
|
|
|
|
for v in 0 ..< committee.len * 2 div 3 + 1:
|
|
|
|
aggregation_bits[v] = true
|
|
|
|
|
|
|
|
attestations.add Attestation(
|
|
|
|
aggregation_bits: aggregation_bits,
|
2022-03-16 07:20:40 +00:00
|
|
|
data: makeAttestationData(state[], getStateField(state[], slot),
|
2022-01-08 23:28:49 +00:00
|
|
|
committee_index, blockRef.get().root)
|
2020-07-09 09:29:32 +00:00
|
|
|
# signature: ValidatorSig()
|
|
|
|
)
|
|
|
|
|
2020-07-15 10:44:18 +00:00
|
|
|
cache = StateCache()
|
2020-07-09 09:29:32 +00:00
|
|
|
|
|
|
|
# -------------------------------------------------------------
|
|
|
|
# Prune
|
|
|
|
|
2021-06-01 11:13:40 +00:00
|
|
|
doAssert: dag.finalizedHead.slot != 0
|
2020-07-09 09:29:32 +00:00
|
|
|
|
2020-07-25 19:41:12 +00:00
|
|
|
pool[].prune()
|
2020-08-27 07:34:12 +00:00
|
|
|
doAssert: b10.root notin pool.forkChoice.backend
|
2020-07-09 09:29:32 +00:00
|
|
|
|
|
|
|
# Add back the old block to ensure we have a duplicate error
|
Backfill support for ChainDAG (#3171)
In the ChainDAG, 3 block pointers are kept: genesis, tail and head. This
PR adds one more block pointer: the backfill block which represents the
block that has been backfilled so far.
When doing a checkpoint sync, a random block is given as starting point
- this is the tail block, and we require that the tail block has a
corresponding state.
When backfilling, we end up with blocks without corresponding states,
hence we cannot use `tail` as a backfill pointer - there is no state.
Nonetheless, we need to keep track of where we are in the backfill
process between restarts, such that we can answer GetBeaconBlocksByRange
requests.
This PR adds the basic support for backfill handling - it needs to be
integrated with backfill sync, and the REST API needs to be adjusted to
take advantage of the new backfilled blocks when responding to certain
requests.
Future work will also enable moving the tail in either direction:
* pruning means moving the tail forward in time and removing states
* backwards means recreating past states from genesis, such that
intermediate states are recreated step by step all the way to the tail -
at that point, tail, genesis and backfill will match up.
* backfilling is done when backfill != genesis - later, this will be the
WSS checkpoint instead
2021-12-13 13:36:06 +00:00
|
|
|
let b10Add_clone = dag.addHeadBlock(verifier, b10_clone) do (
|
2021-08-12 13:08:20 +00:00
|
|
|
blckRef: BlockRef, signedBlock: phase0.TrustedSignedBeaconBlock,
|
2021-06-21 08:35:24 +00:00
|
|
|
epochRef: EpochRef):
|
2020-07-22 09:42:55 +00:00
|
|
|
# Callback add to fork choice if valid
|
2021-12-21 18:56:08 +00:00
|
|
|
pool[].addForkChoice(
|
2022-01-11 10:01:54 +00:00
|
|
|
epochRef, blckRef, signedBlock.message, blckRef.slot.start_beacon_time)
|
2020-07-22 09:42:55 +00:00
|
|
|
|
2021-12-06 09:49:01 +00:00
|
|
|
doAssert: b10Add_clone.error == BlockError.Duplicate
|