Less risk for Eth1-induced delays in block proposal
This commit is contained in:
parent
38f7558e50
commit
4eaf29875a
|
@ -389,6 +389,10 @@ proc pruneOldBlocks(m: Eth1Monitor, depositIndex: uint64) =
|
||||||
eth1Block: lastBlock.voteData.block_hash,
|
eth1Block: lastBlock.voteData.block_hash,
|
||||||
depositContractState: m.eth2FinalizedDepositsMerkleizer.toDepositContractState)
|
depositContractState: m.eth2FinalizedDepositsMerkleizer.toDepositContractState)
|
||||||
|
|
||||||
|
debug "Eth1 blocks pruned",
|
||||||
|
newTailBlock = lastBlock.voteData.block_hash,
|
||||||
|
depositsCount = lastBlock.voteData.deposit_count
|
||||||
|
|
||||||
proc advanceMerkleizer(eth1Chain: Eth1Chain,
|
proc advanceMerkleizer(eth1Chain: Eth1Chain,
|
||||||
merkleizer: var DepositsMerkleizer,
|
merkleizer: var DepositsMerkleizer,
|
||||||
depositIndex: uint64): bool =
|
depositIndex: uint64): bool =
|
||||||
|
@ -434,39 +438,61 @@ proc getDepositsRange(eth1Chain: Eth1Chain, first, last: uint64): seq[Deposit] =
|
||||||
if globalIdx >= first and globalIdx < last:
|
if globalIdx >= first and globalIdx < last:
|
||||||
result.add Deposit(data: blk.deposits[i])
|
result.add Deposit(data: blk.deposits[i])
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/validator.md#get_eth1_data
|
proc lowerBound(chain: Eth1Chain, depositCount: uint64): Eth1Block =
|
||||||
proc getBlockProposalData*(m: Eth1Monitor,
|
# TODO: This can be replaced with a proper binary search in the
|
||||||
state: BeaconState,
|
# future, but the `algorithm` module currently requires an
|
||||||
finalizedEth1Data: Eth1Data,
|
# `openArray`, which the `deques` module can't provide yet.
|
||||||
finalizedStateDepositIndex: uint64): BlockProposalEth1Data =
|
for eth1Block in chain.blocks:
|
||||||
let finalizedEth1Block = m.eth1Chain.findBlock(finalizedEth1Data)
|
if eth1Block.voteData.deposit_count > depositCount:
|
||||||
let hasLatestDeposits = if finalizedEth1Block != nil:
|
return
|
||||||
if finalizedEth1Block.voteData.deposit_root == finalizedEth1Data.deposit_root:
|
result = eth1Block
|
||||||
finalizedEth1Block.voteDataVerified = true
|
|
||||||
|
proc trackFinalizedState*(m: Eth1Monitor,
|
||||||
|
finalizedEth1Data: Eth1Data,
|
||||||
|
finalizedStateDepositIndex: uint64): bool =
|
||||||
|
# Returns true if the Eth1Monitor is synced to the finalization point
|
||||||
|
if m.eth1Chain.blocks.len == 0:
|
||||||
|
debug "Eth1 chain not initialized"
|
||||||
|
return false
|
||||||
|
|
||||||
|
let latest = m.eth1Chain.blocks.peekLast
|
||||||
|
if latest.voteData.deposit_count < finalizedEth1Data.deposit_count:
|
||||||
|
debug "Eth1 chain not synced",
|
||||||
|
ourDepositsCount = latest.voteData.deposit_count,
|
||||||
|
targetDepositsCount = finalizedEth1Data.deposit_count
|
||||||
|
return false
|
||||||
|
|
||||||
|
let matchingBlock = m.eth1Chain.lowerBound(finalizedEth1Data.deposit_count)
|
||||||
|
result = if matchingBlock != nil:
|
||||||
|
if matchingBlock.voteData.deposit_root == finalizedEth1Data.deposit_root:
|
||||||
|
matchingBlock.voteDataVerified = true
|
||||||
true
|
true
|
||||||
else:
|
else:
|
||||||
error "Corrupted deposits history detected",
|
error "Corrupted deposits history detected",
|
||||||
|
depositsCount = finalizedEth1Data.deposit_count,
|
||||||
targetDepositsRoot = finalizedEth1Data.deposit_root,
|
targetDepositsRoot = finalizedEth1Data.deposit_root,
|
||||||
targetDepositsCount = finalizedEth1Data.deposit_count,
|
ourDepositsRoot = matchingBlock.voteData.deposit_root
|
||||||
ourDepositsCount = finalizedEth1Block.voteData.deposit_count,
|
|
||||||
ourDepositsRoot = finalizedEth1Block.voteData.deposit_root
|
|
||||||
false
|
false
|
||||||
else:
|
else:
|
||||||
debug "Finalized Eth1 checkpoint not present in local chain",
|
error "The Eth1 chain is in inconsistent state",
|
||||||
checkpointHash = finalizedEth1Data.block_hash,
|
checkpointHash = finalizedEth1Data.block_hash,
|
||||||
checkpointDeposits = finalizedEth1Data.deposit_count,
|
checkpointDeposits = finalizedEth1Data.deposit_count,
|
||||||
localChainStart = shortLog(m.eth1Chain.blocks.peekFirst),
|
localChainStart = shortLog(m.eth1Chain.blocks.peekFirst),
|
||||||
localChainEnd = shortLog(m.eth1Chain.blocks.peekLast)
|
localChainEnd = shortLog(m.eth1Chain.blocks.peekLast)
|
||||||
false
|
false
|
||||||
|
|
||||||
if hasLatestDeposits:
|
if result:
|
||||||
# TODO(zah)
|
|
||||||
# To make block proposal cheaper, we can perform this action more regularly
|
|
||||||
# (e.g. in BeaconNode.onSlot). But keep in mind that this action needs to be
|
|
||||||
# performed only when there are validators attached to the node.
|
|
||||||
m.pruneOldBlocks(finalizedStateDepositIndex)
|
m.pruneOldBlocks(finalizedStateDepositIndex)
|
||||||
|
|
||||||
let periodStart = voting_period_start_time(state)
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/validator.md#get_eth1_data
|
||||||
|
proc getBlockProposalData*(m: Eth1Monitor,
|
||||||
|
state: BeaconState,
|
||||||
|
finalizedEth1Data: Eth1Data,
|
||||||
|
finalizedStateDepositIndex: uint64): BlockProposalEth1Data =
|
||||||
|
let
|
||||||
|
periodStart = voting_period_start_time(state)
|
||||||
|
hasLatestDeposits = m.trackFinalizedState(finalizedEth1Data,
|
||||||
|
finalizedStateDepositIndex)
|
||||||
|
|
||||||
var otherVotesCountTable = initCountTable[Eth1Data]()
|
var otherVotesCountTable = initCountTable[Eth1Data]()
|
||||||
for vote in state.eth1_data_votes:
|
for vote in state.eth1_data_votes:
|
||||||
|
@ -648,11 +674,6 @@ proc syncBlockRange(m: Eth1Monitor,
|
||||||
debug.logTime "Deposits grouped in blocks":
|
debug.logTime "Deposits grouped in blocks":
|
||||||
let blocksWithDeposits = depositEventsToBlocks(depositLogs)
|
let blocksWithDeposits = depositEventsToBlocks(depositLogs)
|
||||||
|
|
||||||
var
|
|
||||||
# A temporary sequence for stroing all new blocks aiming to make the
|
|
||||||
# updates to m.eth1Chain more atomic/transactional.
|
|
||||||
blocksToAddToChain = newSeq[Eth1Block]()
|
|
||||||
|
|
||||||
for i in 0 ..< blocksWithDeposits.len:
|
for i in 0 ..< blocksWithDeposits.len:
|
||||||
let blk = blocksWithDeposits[i]
|
let blk = blocksWithDeposits[i]
|
||||||
|
|
||||||
|
@ -664,14 +685,13 @@ proc syncBlockRange(m: Eth1Monitor,
|
||||||
blk.voteData.deposit_root = merkleizer[].getDepositsRoot
|
blk.voteData.deposit_root = merkleizer[].getDepositsRoot
|
||||||
|
|
||||||
if blk.number > fullSyncFromBlock:
|
if blk.number > fullSyncFromBlock:
|
||||||
let lastBlock = if blocksToAddToChain.len > 0: blocksToAddToChain[^1]
|
let lastBlock = m.eth1Chain.blocks.peekLast
|
||||||
else: m.eth1Chain.blocks.peekLast
|
|
||||||
for n in max(lastBlock.number + 1, fullSyncFromBlock) ..< blk.number:
|
for n in max(lastBlock.number + 1, fullSyncFromBlock) ..< blk.number:
|
||||||
let blockWithoutDeposits = await m.dataProvider.getBlockByNumber(n)
|
let blockWithoutDeposits = await m.dataProvider.getBlockByNumber(n)
|
||||||
blocksToAddToChain.add(
|
m.eth1Chain.addBlock(
|
||||||
lastBlock.makeSuccessorWithoutDeposits(blockWithoutDeposits))
|
lastBlock.makeSuccessorWithoutDeposits(blockWithoutDeposits))
|
||||||
|
|
||||||
blocksToAddToChain.add blk
|
m.eth1Chain.addBlock blk
|
||||||
|
|
||||||
if blocksWithDeposits.len > 0:
|
if blocksWithDeposits.len > 0:
|
||||||
let lastIdx = blocksWithDeposits.len - 1
|
let lastIdx = blocksWithDeposits.len - 1
|
||||||
|
@ -697,8 +717,7 @@ proc syncBlockRange(m: Eth1Monitor,
|
||||||
raise newException(CorruptDataProvider,
|
raise newException(CorruptDataProvider,
|
||||||
"The deposit log events disagree with the deposit contract state")
|
"The deposit log events disagree with the deposit contract state")
|
||||||
of VerifiedCorrect:
|
of VerifiedCorrect:
|
||||||
for blk in blocksToAddToChain:
|
lastBlock.voteDataVerified = true
|
||||||
blk.voteDataVerified = true
|
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
@ -706,9 +725,6 @@ proc syncBlockRange(m: Eth1Monitor,
|
||||||
blockNumber = lastBlock.number,
|
blockNumber = lastBlock.number,
|
||||||
depositsProcessed = lastBlock.voteData.deposit_count
|
depositsProcessed = lastBlock.voteData.deposit_count
|
||||||
|
|
||||||
for blk in blocksToAddToChain:
|
|
||||||
m.eth1Chain.addBlock blk
|
|
||||||
|
|
||||||
when hasGenesisDetection:
|
when hasGenesisDetection:
|
||||||
if m.genesisStateFut != nil:
|
if m.genesisStateFut != nil:
|
||||||
for blk in blocksWithDeposits:
|
for blk in blocksWithDeposits:
|
||||||
|
@ -798,6 +814,8 @@ proc startEth1Syncing(m: Eth1Monitor) {.async.} =
|
||||||
var eth1SyncedTo = Eth1BlockNumber startBlock.number
|
var eth1SyncedTo = Eth1BlockNumber startBlock.number
|
||||||
var scratchMerkleizer = newClone(copy m.eth2FinalizedDepositsMerkleizer)
|
var scratchMerkleizer = newClone(copy m.eth2FinalizedDepositsMerkleizer)
|
||||||
|
|
||||||
|
debug "Starting Eth1 syncing", `from` = shortLog(m.eth1Chain.blocks[0])
|
||||||
|
|
||||||
while true:
|
while true:
|
||||||
if bnStatus == BeaconNodeStatus.Stopping:
|
if bnStatus == BeaconNodeStatus.Stopping:
|
||||||
when hasGenesisDetection:
|
when hasGenesisDetection:
|
||||||
|
|
|
@ -51,7 +51,7 @@ proc installValidatorApiHandlers*(rpcServer: RpcServer, node: BeaconNode) =
|
||||||
if head.slot >= body.message.slot:
|
if head.slot >= body.message.slot:
|
||||||
raise newException(CatchableError,
|
raise newException(CatchableError,
|
||||||
"Proposal is for a past slot: " & $body.message.slot)
|
"Proposal is for a past slot: " & $body.message.slot)
|
||||||
if head == await proposeSignedBlock(node, head, AttachedValidator(), body):
|
if head == proposeSignedBlock(node, head, AttachedValidator(), body):
|
||||||
raise newException(CatchableError, "Could not propose block")
|
raise newException(CatchableError, "Could not propose block")
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
|
@ -264,10 +264,9 @@ proc makeBeaconBlockForHeadAndSlot*(node: BeaconNode,
|
||||||
proc proposeSignedBlock*(node: BeaconNode,
|
proc proposeSignedBlock*(node: BeaconNode,
|
||||||
head: BlockRef,
|
head: BlockRef,
|
||||||
validator: AttachedValidator,
|
validator: AttachedValidator,
|
||||||
newBlock: SignedBeaconBlock): Future[BlockRef] {.async.} =
|
newBlock: SignedBeaconBlock): BlockRef =
|
||||||
|
|
||||||
let newBlockRef = node.chainDag.addRawBlock(node.quarantine,
|
let newBlockRef = node.chainDag.addRawBlock(node.quarantine, newBlock) do (
|
||||||
newBlock) do (
|
|
||||||
blckRef: BlockRef, signedBlock: SignedBeaconBlock,
|
blckRef: BlockRef, signedBlock: SignedBeaconBlock,
|
||||||
epochRef: EpochRef, state: HashedBeaconState):
|
epochRef: EpochRef, state: HashedBeaconState):
|
||||||
# Callback add to fork choice if valid
|
# Callback add to fork choice if valid
|
||||||
|
@ -348,7 +347,7 @@ proc proposeBlock(node: BeaconNode,
|
||||||
newBlock.signature = await validator.signBlockProposal(
|
newBlock.signature = await validator.signBlockProposal(
|
||||||
fork, genesis_validators_root, slot, newBlock.root)
|
fork, genesis_validators_root, slot, newBlock.root)
|
||||||
|
|
||||||
return await node.proposeSignedBlock(head, validator, newBlock)
|
return node.proposeSignedBlock(head, validator, newBlock)
|
||||||
|
|
||||||
proc handleAttestations(node: BeaconNode, head: BlockRef, slot: Slot) =
|
proc handleAttestations(node: BeaconNode, head: BlockRef, slot: Slot) =
|
||||||
## Perform all attestations that the validators attached to this node should
|
## Perform all attestations that the validators attached to this node should
|
||||||
|
@ -688,3 +687,9 @@ proc handleValidatorDuties*(node: BeaconNode, lastSlot, slot: Slot) {.async.} =
|
||||||
aggregationHead = get_ancestor(head, aggregationSlot)
|
aggregationHead = get_ancestor(head, aggregationSlot)
|
||||||
|
|
||||||
await broadcastAggregatedAttestations(node, aggregationHead, aggregationSlot)
|
await broadcastAggregatedAttestations(node, aggregationHead, aggregationSlot)
|
||||||
|
|
||||||
|
if node.eth1Monitor != nil and (slot mod SLOTS_PER_EPOCH) == 0:
|
||||||
|
let finalizedEpochRef = node.chainDag.getFinalizedEpochRef()
|
||||||
|
discard node.eth1Monitor.trackFinalizedState(
|
||||||
|
finalizedEpochRef.eth1_data, finalizedEpochRef.eth1_deposit_index)
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 852b707b5daa99c380b716c8efe49807b8bfd4f0
|
Subproject commit 1d2ca5b059db7591c044d5d2fa5e5cd3e98b21a7
|
Loading…
Reference in New Issue