return block result details (#1049)

This commit is contained in:
Jacek Sieka 2020-05-21 19:08:31 +02:00 committed by GitHub
parent 04045ae943
commit 7fbb8c0bc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 53 additions and 40 deletions

View File

@ -290,7 +290,8 @@ proc onAttestation(node: BeaconNode, attestation: Attestation) =
node.attestationPool.add(attestation) node.attestationPool.add(attestation)
proc storeBlock(node: BeaconNode, signedBlock: SignedBeaconBlock): bool = proc storeBlock(
node: BeaconNode, signedBlock: SignedBeaconBlock): Result[void, BlockError] =
let blockRoot = hash_tree_root(signedBlock.message) let blockRoot = hash_tree_root(signedBlock.message)
debug "Block received", debug "Block received",
signedBlock = shortLog(signedBlock.message), signedBlock = shortLog(signedBlock.message),
@ -302,8 +303,7 @@ proc storeBlock(node: BeaconNode, signedBlock: SignedBeaconBlock): bool =
dump(node.config.dumpDir / "incoming", signedBlock, blockRoot) dump(node.config.dumpDir / "incoming", signedBlock, blockRoot)
beacon_blocks_received.inc() beacon_blocks_received.inc()
if node.blockPool.add(blockRoot, signedBlock).isNil: discard ? node.blockPool.add(blockRoot, signedBlock)
return false
# 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 they block # all of them. Let's add them to the attestation pool - in case they block
@ -315,7 +315,7 @@ proc storeBlock(node: BeaconNode, signedBlock: SignedBeaconBlock): bool =
signedBlock.message.slot.epoch + 1 >= currentSlot.slot.epoch: signedBlock.message.slot.epoch + 1 >= currentSlot.slot.epoch:
for attestation in signedBlock.message.body.attestations: for attestation in signedBlock.message.body.attestations:
node.onAttestation(attestation) node.onAttestation(attestation)
return true ok()
proc onBeaconBlock(node: BeaconNode, signedBlock: SignedBeaconBlock) = proc onBeaconBlock(node: BeaconNode, signedBlock: SignedBeaconBlock) =
# We received a block but don't know much about it yet - in particular, we # We received a block but don't know much about it yet - in particular, we
@ -525,7 +525,7 @@ proc runSyncLoop(node: BeaconNode) {.async.} =
local_head_slot = getLocalHeadSlot() local_head_slot = getLocalHeadSlot()
let sm = now(chronos.Moment) let sm = now(chronos.Moment)
for blk in list: for blk in list:
if not(node.storeBlock(blk)): if node.storeBlock(blk).isErr:
return false return false
discard node.updateHead() discard node.updateHead()

View File

@ -7,12 +7,15 @@
import import
extras, beacon_chain_db, extras, beacon_chain_db,
stew/results,
spec/[crypto, datatypes, digest] spec/[crypto, datatypes, digest]
import import
block_pools/[block_pools_types, clearance, candidate_chains, quarantine] block_pools/[block_pools_types, clearance, candidate_chains, quarantine]
export results
# Block_Pools # Block_Pools
# -------------------------------------------- # --------------------------------------------
# #
@ -51,7 +54,7 @@ template finalizedHead*(pool: BlockPool): BlockSlot =
pool.dag.finalizedHead pool.dag.finalizedHead
proc add*(pool: var BlockPool, blockRoot: Eth2Digest, proc add*(pool: var BlockPool, blockRoot: Eth2Digest,
signedBlock: SignedBeaconBlock): BlockRef {.gcsafe.} = signedBlock: SignedBeaconBlock): Result[BlockRef, BlockError] {.gcsafe.} =
add(pool.dag, pool.quarantine, blockRoot, signedBlock) add(pool.dag, pool.quarantine, blockRoot, signedBlock)
export parent # func parent*(bs: BlockSlot): BlockSlot export parent # func parent*(bs: BlockSlot): BlockSlot

View File

@ -23,6 +23,11 @@ import
# the last finalized block known. # the last finalized block known.
type type
BlockError* = enum
MissingParent
Old
Invalid
Quarantine* = object Quarantine* = object
## Keeps track of unsafe blocks coming from the network ## Keeps track of unsafe blocks coming from the network
## and that cannot be added to the chain ## and that cannot be added to the chain

View File

@ -7,12 +7,14 @@
import import
chronicles, tables, chronicles, tables,
metrics, metrics, stew/results,
../ssz, ../state_transition, ../extras, ../ssz, ../state_transition, ../extras,
../spec/[crypto, datatypes, digest, helpers], ../spec/[crypto, datatypes, digest, helpers],
block_pools_types, candidate_chains block_pools_types, candidate_chains
export results
# Clearance # Clearance
# --------------------------------------------- # ---------------------------------------------
# #
@ -34,7 +36,7 @@ func getOrResolve*(dag: CandidateChains, quarantine: var Quarantine, root: Eth2D
proc add*( proc add*(
dag: var CandidateChains, quarantine: var Quarantine, dag: var CandidateChains, quarantine: var Quarantine,
blockRoot: Eth2Digest, blockRoot: Eth2Digest,
signedBlock: SignedBeaconBlock): BlockRef {.gcsafe.} signedBlock: SignedBeaconBlock): Result[BlockRef, BlockError] {.gcsafe.}
proc addResolvedBlock( proc addResolvedBlock(
dag: var CandidateChains, quarantine: var Quarantine, dag: var CandidateChains, quarantine: var Quarantine,
@ -105,7 +107,7 @@ proc addResolvedBlock(
proc add*( proc add*(
dag: var CandidateChains, quarantine: var Quarantine, dag: var CandidateChains, quarantine: var Quarantine,
blockRoot: Eth2Digest, blockRoot: Eth2Digest,
signedBlock: SignedBeaconBlock): BlockRef {.gcsafe.} = signedBlock: SignedBeaconBlock): Result[BlockRef, BlockError] {.gcsafe.} =
## return the block, if resolved... ## return the block, if resolved...
## the state parameter may be updated to include the given block, if ## the state parameter may be updated to include the given block, if
## everything checks out ## everything checks out
@ -122,7 +124,7 @@ proc add*(
blockRoot = shortLog(blockRoot), blockRoot = shortLog(blockRoot),
cat = "filtering" cat = "filtering"
return blockRef[] return ok blockRef[]
quarantine.missing.del(blockRoot) quarantine.missing.del(blockRoot)
@ -138,7 +140,7 @@ proc add*(
blockRoot = shortLog(blockRoot), blockRoot = shortLog(blockRoot),
cat = "filtering" cat = "filtering"
return return err Old
let parent = dag.blocks.getOrDefault(blck.parent_root) let parent = dag.blocks.getOrDefault(blck.parent_root)
@ -150,7 +152,7 @@ proc add*(
blockRoot = shortLog(blockRoot), blockRoot = shortLog(blockRoot),
parentBlock = shortLog(parent) parentBlock = shortLog(parent)
return return err Invalid
# The block might have been in either of pending or missing - we don't want # The block might have been in either of pending or missing - we don't want
# any more work done on its behalf # any more work done on its behalf
@ -181,7 +183,7 @@ proc add*(
blockRoot = shortLog(blockRoot), blockRoot = shortLog(blockRoot),
cat = "filtering" cat = "filtering"
return return err Invalid
# Careful, tmpState.data has been updated but not blck - we need to create # Careful, tmpState.data has been updated but not blck - we need to create
# the BlockRef first! # the BlockRef first!
dag.tmpState.blck = addResolvedBlock( dag.tmpState.blck = addResolvedBlock(
@ -189,7 +191,7 @@ proc add*(
dag.tmpState.data.data, blockRoot, signedBlock, parent) dag.tmpState.data.data, blockRoot, signedBlock, parent)
dag.putState(dag.tmpState.data, dag.tmpState.blck) dag.putState(dag.tmpState.data, dag.tmpState.blck)
return dag.tmpState.blck return ok dag.tmpState.blck
# TODO already checked hash though? main reason to keep this is because # TODO already checked hash though? main reason to keep this is because
# the pending dag calls this function back later in a loop, so as long # the pending dag calls this function back later in a loop, so as long
@ -204,7 +206,7 @@ proc add*(
if blck.parent_root in quarantine.missing or if blck.parent_root in quarantine.missing or
blck.parent_root in quarantine.pending: blck.parent_root in quarantine.pending:
return return err MissingParent
# This is an unresolved block - put its parent on the missing list for now... # This is an unresolved block - put its parent on the missing list for now...
# TODO if we receive spam blocks, one heurestic to implement might be to wait # TODO if we receive spam blocks, one heurestic to implement might be to wait
@ -239,6 +241,8 @@ proc add*(
missing = quarantine.missing.len, missing = quarantine.missing.len,
cat = "filtering" cat = "filtering"
return err MissingParent
# https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/specs/phase0/p2p-interface.md#global-topics # https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/specs/phase0/p2p-interface.md#global-topics
proc isValidBeaconBlock*( proc isValidBeaconBlock*(
dag: CandidateChains, quarantine: var Quarantine, dag: CandidateChains, quarantine: var Quarantine,

View File

@ -189,30 +189,31 @@ proc proposeBlock(node: BeaconNode,
(blockRoot, newBlock) (blockRoot, newBlock)
let newBlockRef = node.blockPool.add(nroot, nblck) let newBlockRef = node.blockPool.add(nroot, nblck)
if newBlockRef == nil: if newBlockRef.isErr:
warn "Unable to add proposed block to block pool", warn "Unable to add proposed block to block pool",
newBlock = shortLog(newBlock.message), newBlock = shortLog(newBlock.message),
blockRoot = shortLog(blockRoot), blockRoot = shortLog(blockRoot),
cat = "bug" cat = "bug"
return head return head
info "Block proposed", info "Block proposed",
blck = shortLog(newBlock.message), blck = shortLog(newBlock.message),
blockRoot = shortLog(newBlockRef.root), blockRoot = shortLog(newBlockRef[].root),
validator = shortLog(validator), validator = shortLog(validator),
cat = "consensus" cat = "consensus"
if node.config.dumpEnabled: if node.config.dumpEnabled:
dump(node.config.dumpDir, newBlock, newBlockRef) dump(node.config.dumpDir, newBlock, newBlockRef[])
node.blockPool.withState( node.blockPool.withState(
node.blockPool.tmpState, newBlockRef.atSlot(newBlockRef.slot)): node.blockPool.tmpState, newBlockRef[].atSlot(newBlockRef[].slot)):
dump(node.config.dumpDir, hashedState, newBlockRef) dump(node.config.dumpDir, hashedState, newBlockRef[])
node.network.broadcast(node.topicBeaconBlocks, newBlock) node.network.broadcast(node.topicBeaconBlocks, newBlock)
beacon_blocks_proposed.inc() beacon_blocks_proposed.inc()
return newBlockRef return newBlockRef[]
proc handleAttestations(node: BeaconNode, head: BlockRef, slot: Slot) = proc handleAttestations(node: BeaconNode, head: BlockRef, slot: Slot) =

View File

@ -130,7 +130,7 @@ cli do(slots = SLOTS_PER_EPOCH * 6,
state.fork, state.genesis_validators_root, newBlock.message.slot, state.fork, state.genesis_validators_root, newBlock.message.slot,
blockRoot, privKey) blockRoot, privKey)
let added = blockPool.add(blockRoot, newBlock) let added = blockPool.add(blockRoot, newBlock).tryGet()
blockPool.updateHead(added) blockPool.updateHead(added)
for i in 0..<slots: for i in 0..<slots:

View File

@ -152,7 +152,7 @@ suiteReport "Attestation pool processing" & preset():
let let
b1 = addTestBlock(state.data.data, blockPool.tail.root) b1 = addTestBlock(state.data.data, blockPool.tail.root)
b1Root = hash_tree_root(b1.message) b1Root = hash_tree_root(b1.message)
b1Add = blockPool.add(b1Root, b1) b1Add = blockPool.add(b1Root, b1)[]
head = pool.selectHead() head = pool.selectHead()
check: check:
@ -161,7 +161,7 @@ suiteReport "Attestation pool processing" & preset():
let let
b2 = addTestBlock(state.data.data, b1Root) b2 = addTestBlock(state.data.data, b1Root)
b2Root = hash_tree_root(b2.message) b2Root = hash_tree_root(b2.message)
b2Add = blockPool.add(b2Root, b2) b2Add = blockPool.add(b2Root, b2)[]
head2 = pool.selectHead() head2 = pool.selectHead()
check: check:
@ -172,7 +172,7 @@ suiteReport "Attestation pool processing" & preset():
let let
b10 = makeTestBlock(state.data.data, blockPool.tail.root) b10 = makeTestBlock(state.data.data, blockPool.tail.root)
b10Root = hash_tree_root(b10.message) b10Root = hash_tree_root(b10.message)
b10Add = blockPool.add(b10Root, b10) b10Add = blockPool.add(b10Root, b10)[]
head = pool.selectHead() head = pool.selectHead()
check: check:
@ -183,7 +183,7 @@ suiteReport "Attestation pool processing" & preset():
graffiti = Eth2Digest(data: [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]) graffiti = Eth2Digest(data: [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])
) )
b11Root = hash_tree_root(b11.message) b11Root = hash_tree_root(b11.message)
b11Add = blockPool.add(b11Root, b11) b11Add = blockPool.add(b11Root, b11)[]
bc1 = get_beacon_committee( bc1 = get_beacon_committee(
state.data.data, state.data.data.slot, 1.CommitteeIndex, cache) state.data.data, state.data.data.slot, 1.CommitteeIndex, cache)

View File

@ -110,7 +110,7 @@ suiteReport "Block pool processing" & preset():
timedTest "Simple block add&get" & preset(): timedTest "Simple block add&get" & preset():
let let
b1Add = pool.add(b1Root, b1) b1Add = pool.add(b1Root, b1)[]
b1Get = pool.get(b1Root) b1Get = pool.get(b1Root)
check: check:
@ -121,7 +121,7 @@ suiteReport "Block pool processing" & preset():
pool.heads[0].blck == b1Add pool.heads[0].blck == b1Add
let let
b2Add = pool.add(b2Root, b2) b2Add = pool.add(b2Root, b2)[]
b2Get = pool.get(b2Root) b2Get = pool.get(b2Root)
check: check:
@ -138,7 +138,7 @@ suiteReport "Block pool processing" & preset():
let let
b4 = addTestBlock(stateData.data.data, b2Root) b4 = addTestBlock(stateData.data.data, b2Root)
b4Root = hash_tree_root(b4.message) b4Root = hash_tree_root(b4.message)
b4Add = pool.add(b4Root, b4) b4Add = pool.add(b4Root, b4)[]
# TODO fix addTestBlock to work on HashedBeaconState # TODO fix addTestBlock to work on HashedBeaconState
stateData.data.root = hash_tree_root(stateData.data.data) stateData.data.root = hash_tree_root(stateData.data.data)
@ -176,13 +176,13 @@ suiteReport "Block pool processing" & preset():
blocks[0..<2] == [BlockRef nil, nil] # block 3 is missing! blocks[0..<2] == [BlockRef nil, nil] # block 3 is missing!
timedTest "Reverse order block add & get" & preset(): timedTest "Reverse order block add & get" & preset():
discard pool.add(b2Root, b2) check: pool.add(b2Root, b2).error == MissingParent
check: check:
pool.get(b2Root).isNone() # Unresolved, shouldn't show up pool.get(b2Root).isNone() # Unresolved, shouldn't show up
FetchRecord(root: b1Root, historySlots: 1) in pool.checkMissing() FetchRecord(root: b1Root, historySlots: 1) in pool.checkMissing()
discard pool.add(b1Root, b1) check: pool.add(b1Root, b1).isOk
let let
b1Get = pool.get(b1Root) b1Get = pool.get(b1Root)
@ -217,8 +217,8 @@ suiteReport "Block pool processing" & preset():
timedTest "Can add same block twice" & preset(): timedTest "Can add same block twice" & preset():
let let
b10 = pool.add(b1Root, b1) b10 = pool.add(b1Root, b1)[]
b11 = pool.add(b1Root, b1) b11 = pool.add(b1Root, b1)[]
check: check:
b10 == b11 b10 == b11
@ -226,7 +226,7 @@ suiteReport "Block pool processing" & preset():
timedTest "updateHead updates head and headState" & preset(): timedTest "updateHead updates head and headState" & preset():
let let
b1Add = pool.add(b1Root, b1) b1Add = pool.add(b1Root, b1)[]
pool.updateHead(b1Add) pool.updateHead(b1Add)
@ -236,8 +236,8 @@ suiteReport "Block pool processing" & preset():
timedTest "updateStateData sanity" & preset(): timedTest "updateStateData sanity" & preset():
let let
b1Add = pool.add(b1Root, b1) b1Add = pool.add(b1Root, b1)[]
b2Add = pool.add(b2Root, b2) b2Add = pool.add(b2Root, b2)[]
bs1 = BlockSlot(blck: b1Add, slot: b1.message.slot) bs1 = BlockSlot(blck: b1Add, slot: b1.message.slot)
bs1_3 = b1Add.atSlot(3.Slot) bs1_3 = b1Add.atSlot(3.Slot)
bs2_3 = b2Add.atSlot(3.Slot) bs2_3 = b2Add.atSlot(3.Slot)
@ -296,7 +296,7 @@ when const_preset == "minimal": # These require some minutes in mainnet
# Create a fork that will not be taken # Create a fork that will not be taken
var var
blck = makeTestBlock(pool.headState.data.data, pool.head.blck.root) blck = makeTestBlock(pool.headState.data.data, pool.head.blck.root)
discard pool.add(hash_tree_root(blck.message), blck) check: pool.add(hash_tree_root(blck.message), blck).isOk
for i in 0 ..< (SLOTS_PER_EPOCH * 6): for i in 0 ..< (SLOTS_PER_EPOCH * 6):
if i == 1: if i == 1:
@ -311,7 +311,7 @@ when const_preset == "minimal": # These require some minutes in mainnet
attestations = makeFullAttestations( attestations = makeFullAttestations(
pool.headState.data.data, pool.head.blck.root, pool.headState.data.data, pool.head.blck.root,
pool.headState.data.data.slot, cache, {})) pool.headState.data.data.slot, cache, {}))
let added = pool.add(hash_tree_root(blck.message), blck) let added = pool.add(hash_tree_root(blck.message), blck)[]
pool.updateHead(added) pool.updateHead(added)
check: check:
@ -342,7 +342,7 @@ when const_preset == "minimal": # These require some minutes in mainnet
attestations = makeFullAttestations( attestations = makeFullAttestations(
pool.headState.data.data, pool.head.blck.root, pool.headState.data.data, pool.head.blck.root,
pool.headState.data.data.slot, cache, {})) pool.headState.data.data.slot, cache, {}))
let added = pool.add(hash_tree_root(blck.message), blck) let added = pool.add(hash_tree_root(blck.message), blck)[]
pool.updateHead(added) pool.updateHead(added)
# Advance past epoch so that the epoch transition is gapped # Advance past epoch so that the epoch transition is gapped
@ -356,7 +356,7 @@ when const_preset == "minimal": # These require some minutes in mainnet
pool.headState.data.data, pool.head.blck.root, pool.headState.data.data, pool.head.blck.root,
pool.headState.data.data.slot, cache, {})) pool.headState.data.data.slot, cache, {}))
let added = pool.add(hash_tree_root(blck.message), blck) let added = pool.add(hash_tree_root(blck.message), blck)[]
pool.updateHead(added) pool.updateHead(added)
let let