Revert "Dual headed fork choice (#1163)" (#1181)

This reverts commit 090f06614a1688205690a8a749b156b5664874ae.
This commit is contained in:
Jacek Sieka 2020-06-16 09:46:00 +02:00 committed by GitHub
parent 89e4819ce9
commit 60176b8cc1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 15 additions and 121 deletions

2
.gitignore vendored
View File

@ -32,9 +32,9 @@ build/
*.sqlite3 *.sqlite3
/local_testnet_data*/ /local_testnet_data*/
/local_testnet*_data*/
# Prometheus db # Prometheus db
/data /data
# Grafana dashboards # Grafana dashboards
/docker/*.json /docker/*.json

View File

@ -23,23 +23,10 @@ func init*(T: type AttestationPool, blockPool: BlockPool): T =
# TODO blockPool is only used when resolving orphaned attestations - it should # TODO blockPool is only used when resolving orphaned attestations - it should
# probably be removed as a dependency of AttestationPool (or some other # probably be removed as a dependency of AttestationPool (or some other
# smart refactoring) # smart refactoring)
# TODO: In tests, on blockpool.init the finalized root
# from the `headState` and `justifiedState` is zero
let forkChoice = initForkChoice(
finalized_block_slot = default(Slot), # This is unnecessary for fork choice but may help external components
finalized_block_state_root = default(Eth2Digest), # This is unnecessary for fork choice but may help external components
justified_epoch = blockPool.headState.data.data.current_justified_checkpoint.epoch,
finalized_epoch = blockPool.headState.data.data.finalized_checkpoint.epoch,
# finalized_root = blockPool.headState.data.data.finalized_checkpoint.root
finalized_root = blockPool.finalizedHead.blck.root
).get()
T( T(
mapSlotsToAttestations: initDeque[AttestationsSeen](), mapSlotsToAttestations: initDeque[AttestationsSeen](),
blockPool: blockPool, blockPool: blockPool,
unresolved: initTable[Eth2Digest, UnresolvedAttestation](), unresolved: initTable[Eth2Digest, UnresolvedAttestation](),
forkChoice_v2: forkChoice
) )
proc combine*(tgt: var Attestation, src: Attestation, flags: UpdateFlags) = proc combine*(tgt: var Attestation, src: Attestation, flags: UpdateFlags) =
@ -121,21 +108,13 @@ proc slotIndex(
func updateLatestVotes( func updateLatestVotes(
pool: var AttestationPool, state: BeaconState, attestationSlot: Slot, pool: var AttestationPool, state: BeaconState, attestationSlot: Slot,
participants: seq[ValidatorIndex], blck: BlockRef) = participants: seq[ValidatorIndex], blck: BlockRef) =
# ForkChoice v2
let target_epoch = compute_epoch_at_slot(attestationSlot)
for validator in participants: for validator in participants:
# ForkChoice v1
let let
pubKey = state.validators[validator].pubkey pubKey = state.validators[validator].pubkey
current = pool.latestAttestations.getOrDefault(pubKey) current = pool.latestAttestations.getOrDefault(pubKey)
if current.isNil or current.slot < attestationSlot: if current.isNil or current.slot < attestationSlot:
pool.latestAttestations[pubKey] = blck pool.latestAttestations[pubKey] = blck
# ForkChoice v2
pool.forkChoice_v2.process_attestation(validator, blck.root, target_epoch)
func get_attesting_indices_seq(state: BeaconState, func get_attesting_indices_seq(state: BeaconState,
attestation_data: AttestationData, attestation_data: AttestationData,
bits: CommitteeValidatorsBits, bits: CommitteeValidatorsBits,
@ -283,34 +262,6 @@ proc add*(pool: var AttestationPool, attestation: Attestation) =
pool.addResolved(blck, attestation) pool.addResolved(blck, attestation)
proc addForkChoice_v2*(pool: var AttestationPool, blck: BlockRef) =
## Add a verified block to the fork choice context
## The current justifiedState of the block pool is used as reference
# TODO: add(BlockPool, blockRoot: Eth2Digest, SignedBeaconBlock): BlockRef
# should ideally return the justified_epoch and finalized_epoch
# so that we can pass them directly to this proc without having to
# redo "updateStateData"
#
# In any case, `updateStateData` should shortcut
# to `getStateDataCached`
updateStateData(
pool.blockPool,
pool.blockPool.tmpState,
BlockSlot(blck: blck, slot: blck.slot)
)
let blockData = pool.blockPool.get(blck)
pool.forkChoice_v2.process_block(
slot = blck.slot,
block_root = blck.root,
parent_root = if not blck.parent.isNil: blck.parent.root else: default(Eth2Digest),
state_root = default(Eth2Digest), # This is unnecessary for fork choice but may help external components
justified_epoch = pool.blockPool.tmpState.data.data.current_justified_checkpoint.epoch,
finalized_epoch = pool.blockPool.tmpState.data.data.finalized_checkpoint.epoch,
).get()
proc getAttestationsForSlot*(pool: AttestationPool, newBlockSlot: Slot): proc getAttestationsForSlot*(pool: AttestationPool, newBlockSlot: Slot):
Option[AttestationsSeen] = Option[AttestationsSeen] =
if newBlockSlot < (GENESIS_SLOT + MIN_ATTESTATION_INCLUSION_DELAY): if newBlockSlot < (GENESIS_SLOT + MIN_ATTESTATION_INCLUSION_DELAY):
@ -445,10 +396,7 @@ proc resolve*(pool: var AttestationPool) =
for a in resolved: for a in resolved:
pool.addResolved(a.blck, a.attestation) pool.addResolved(a.blck, a.attestation)
# Fork choice v1 func latestAttestation*(
# ---------------------------------------------------------------
func latestAttestation(
pool: AttestationPool, pubKey: ValidatorPubKey): BlockRef = pool: AttestationPool, pubKey: ValidatorPubKey): BlockRef =
pool.latestAttestations.getOrDefault(pubKey) pool.latestAttestations.getOrDefault(pubKey)
@ -456,7 +404,7 @@ func latestAttestation(
# The structure of this code differs from the spec since we use a different # The structure of this code differs from the spec since we use a different
# strategy for storing states and justification points - it should nonetheless # strategy for storing states and justification points - it should nonetheless
# be close in terms of functionality. # be close in terms of functionality.
func lmdGhost( func lmdGhost*(
pool: AttestationPool, start_state: BeaconState, pool: AttestationPool, start_state: BeaconState,
start_block: BlockRef): BlockRef = start_block: BlockRef): BlockRef =
# TODO: a Fenwick Tree datastructure to keep track of cumulated votes # TODO: a Fenwick Tree datastructure to keep track of cumulated votes
@ -507,7 +455,7 @@ func lmdGhost(
winCount = candCount winCount = candCount
head = winner head = winner
proc selectHead_v1(pool: AttestationPool): BlockRef = proc selectHead*(pool: AttestationPool): BlockRef =
let let
justifiedHead = pool.blockPool.latestJustifiedBlock() justifiedHead = pool.blockPool.latestJustifiedBlock()
@ -515,47 +463,3 @@ proc selectHead_v1(pool: AttestationPool): BlockRef =
lmdGhost(pool, pool.blockPool.justifiedState.data.data, justifiedHead.blck) lmdGhost(pool, pool.blockPool.justifiedState.data.data, justifiedHead.blck)
newHead newHead
# Fork choice v2
# ---------------------------------------------------------------
func getAttesterBalances(state: StateData): seq[Gwei] {.noInit.}=
## Get the balances from a state
result.newSeq(state.data.data.validators.len) # zero-init
let epoch = state.data.data.slot.compute_epoch_at_slot()
for i in 0 ..< result.len:
# All non-active validators have a 0 balance
template validator: Validator = state.data.data.validators[i]
if validator.is_active_validator(epoch):
result[i] = validator.effective_balance
proc selectHead_v2(pool: var AttestationPool): BlockRef =
let attesterBalances = pool.blockPool.justifiedState.getAttesterBalances()
let newHead = pool.forkChoice_v2.find_head(
justified_epoch = pool.blockPool.justifiedState.data.data.slot.compute_epoch_at_slot(),
justified_root = pool.blockPool.head.justified.blck.root,
finalized_epoch = pool.blockPool.headState.data.data.finalized_checkpoint.epoch,
justified_state_balances = attesterBalances
).get()
pool.blockPool.getRef(newHead)
proc pruneBefore*(pool: var AttestationPool, finalizedhead: BlockSlot) =
pool.forkChoice_v2.maybe_prune(finalizedHead.blck.root).get()
# Dual-Headed Fork choice
# ---------------------------------------------------------------
proc selectHead*(pool: var AttestationPool): BlockRef =
let head_v1 = pool.selectHead_v1()
let head_v2 = pool.selectHead_v2()
if head_v1 != head_v2:
error "Fork choice engines in disagreement, using block from v1.",
v1_block = shortlog(head_v1),
v2_block = shortlog(head_v2)
return head_v1

View File

@ -313,10 +313,6 @@ proc storeBlock(
return err(blck.error) return err(blck.error)
# Still here? This means we received a valid block and we need to add it
# to the fork choice
node.attestationPool.addForkChoice_v2(blck.get())
# The block we received contains attestations, and we might not yet know about # The block we received contains attestations, and we might not yet know about
# all of them. Let's add them to the attestation pool - in case the block # all of them. Let's add them to the attestation pool - in case the block
# is not yet resolved, neither will the attestations be! # is not yet resolved, neither will the attestations be!
@ -1138,3 +1134,4 @@ programMain:
config.depositContractAddress, config.depositContractAddress,
config.depositPrivateKey, config.depositPrivateKey,
delayGenerator) delayGenerator)

View File

@ -68,9 +68,6 @@ proc updateHead*(node: BeaconNode): BlockRef =
node.blockPool.updateHead(newHead) node.blockPool.updateHead(newHead)
beacon_head_root.set newHead.root.toGaugeValue beacon_head_root.set newHead.root.toGaugeValue
# Cleanup the fork choice v2 if we have a finalized head
node.attestationPool.pruneBefore(node.blockPool.finalizedHead)
newHead newHead
template findIt*(s: openarray, predicate: untyped): int64 = template findIt*(s: openarray, predicate: untyped): int64 =

View File

@ -5,8 +5,7 @@ import
stew/endians2, stew/endians2,
spec/[datatypes, crypto, digest], spec/[datatypes, crypto, digest],
block_pools/block_pools_types, block_pools/block_pools_types,
block_pool, # TODO: refactoring compat shim block_pool # TODO: refactoring compat shim
fork_choice/fork_choice_types
export block_pools_types export block_pools_types
@ -75,9 +74,6 @@ type
latestAttestations*: Table[ValidatorPubKey, BlockRef] ##\ latestAttestations*: Table[ValidatorPubKey, BlockRef] ##\
## Map that keeps track of the most recent vote of each attester - see ## Map that keeps track of the most recent vote of each attester - see
## fork_choice ## fork_choice
forkChoice_v2*: ForkChoice ##\
## The alternative fork choice "proto_array" that will ultimately
## replace the original one
# ############################################# # #############################################
# #

View File

@ -117,7 +117,7 @@ func process_attestation*(
vote.next_epoch = target_epoch vote.next_epoch = target_epoch
{.noSideEffect.}: {.noSideEffect.}:
trace "Integrating vote in fork choice", info "Integrating vote in fork choice",
validator_index = $validator_index, validator_index = $validator_index,
new_vote = shortlog(vote) new_vote = shortlog(vote)
else: else:
@ -129,7 +129,7 @@ func process_attestation*(
ignored_block_root = shortlog(block_root), ignored_block_root = shortlog(block_root),
ignored_target_epoch = $target_epoch ignored_target_epoch = $target_epoch
else: else:
trace "Ignoring double-vote for fork choice", info "Ignoring double-vote for fork choice",
validator_index = $validator_index, validator_index = $validator_index,
current_vote = shortlog(vote), current_vote = shortlog(vote),
ignored_block_root = shortlog(block_root), ignored_block_root = shortlog(block_root),
@ -159,7 +159,7 @@ func process_block*(
return err("process_block_error: " & $err) return err("process_block_error: " & $err)
{.noSideEffect.}: {.noSideEffect.}:
trace "Integrating block in fork choice", info "Integrating block in fork choice",
block_root = $shortlog(block_root), block_root = $shortlog(block_root),
parent_root = $shortlog(parent_root), parent_root = $shortlog(parent_root),
justified_epoch = $justified_epoch, justified_epoch = $justified_epoch,
@ -205,7 +205,7 @@ func find_head*(
return err("find_head failed: " & $ghost_err) return err("find_head failed: " & $ghost_err)
{.noSideEffect.}: {.noSideEffect.}:
debug "Fork choice requested", info "Fork choice requested",
justified_epoch = $justified_epoch, justified_epoch = $justified_epoch,
justified_root = shortlog(justified_root), justified_root = shortlog(justified_root),
finalized_epoch = $finalized_epoch, finalized_epoch = $finalized_epoch,

View File

@ -33,7 +33,7 @@ suiteReport "Attestation pool processing" & preset():
check: check:
process_slots(state.data, state.data.data.slot + 1) process_slots(state.data, state.data.data.slot + 1)
pool[].addForkChoice_v2(blockPool[].tail) # Make the tail known to fork choice # pool[].add(blockPool[].tail) # Make the tail known to fork choice
timedTest "Can add and retrieve simple attestation" & preset(): timedTest "Can add and retrieve simple attestation" & preset():
var cache = get_empty_per_epoch_cache() var cache = get_empty_per_epoch_cache()
@ -161,7 +161,7 @@ suiteReport "Attestation pool processing" & preset():
b1Root = hash_tree_root(b1.message) b1Root = hash_tree_root(b1.message)
b1Add = blockpool[].add(b1Root, b1)[] b1Add = blockpool[].add(b1Root, b1)[]
pool[].addForkChoice_v2(b1Add) # pool[].add(b1Add) - make a block known to the future fork choice
let head = pool[].selectHead() let head = pool[].selectHead()
check: check:
@ -172,7 +172,7 @@ suiteReport "Attestation pool processing" & preset():
b2Root = hash_tree_root(b2.message) b2Root = hash_tree_root(b2.message)
b2Add = blockpool[].add(b2Root, b2)[] b2Add = blockpool[].add(b2Root, b2)[]
pool[].addForkChoice_v2(b2Add) # pool[].add(b2Add) - make a block known to the future fork choice
let head2 = pool[].selectHead() let head2 = pool[].selectHead()
check: check:
@ -185,7 +185,7 @@ suiteReport "Attestation pool processing" & preset():
b10Root = hash_tree_root(b10.message) b10Root = hash_tree_root(b10.message)
b10Add = blockpool[].add(b10Root, b10)[] b10Add = blockpool[].add(b10Root, b10)[]
pool[].addForkChoice_v2(b10Add) # pool[].add(b10Add) - make a block known to the future fork choice
let head = pool[].selectHead() let head = pool[].selectHead()
check: check:
@ -202,7 +202,7 @@ suiteReport "Attestation pool processing" & preset():
state.data.data, state.data.data.slot, 1.CommitteeIndex, cache) state.data.data, state.data.data.slot, 1.CommitteeIndex, cache)
attestation0 = makeAttestation(state.data.data, b10Root, bc1[0], cache) attestation0 = makeAttestation(state.data.data, b10Root, bc1[0], cache)
pool[].addForkChoice_v2(b11Add) # pool[].add(b11Add) - make a block known to the future fork choice
pool[].add(attestation0) pool[].add(attestation0)
let head2 = pool[].selectHead() let head2 = pool[].selectHead()