Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attest immediately if block from proposer - fix #966 #1014

Closed
wants to merge 5 commits into from

Conversation

mratsim
Copy link
Contributor

@mratsim mratsim commented May 13, 2020

This PR does 2 things:

  1. Fix Attestation duties: always waiting for 2 seconds #966, when we receive a block from the expected proposer, we attest immediately

  2. BlockRef now stores the justified and finalized checkpoints which will avoid rewinding state in the fork choice PR at https://github.com/status-im/nim-beacon-chain/pull/965/files#diff-a007e749710608c06418bb9fcdf140dbR276-R302, https://github.com/status-im/nim-beacon-chain/blob/7dba780a1d2503c04bcaf360b1c1d8410807dd18/beacon_chain/attestation_pool.nim#L276-L302

@arnetheduck
Copy link
Member

BlockPool.justifiedState exists for fork choice alone, basically - where in fork choice is the finalized checkpoint used?

@arnetheduck
Copy link
Member

Ok so if it's added in BlockRef it should correspondingly be removed from BlockPool.justifiedState - it's a bit of an overhead that I've considered mitigating with something like an EpochRef but it's fine for now - the EpochRef change is more far-reaching in consequences.

@@ -198,6 +202,7 @@ type
## has advanced without blocks

Head* = object
# TODO: delete - all BlockRef tracks the justified checkpoint
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, head still needs to stay..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The field, but it can be a regular BlockRef

func isBlockFromExpectedProposerAtSlot(blck: BlockRef, targetSlot: Slot): bool =
## Returns true if the block is from the expected proposer
##
## This is true if-and-only-if the block slot matches the target slot
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it doesn't check the proposer actually - ie if someone from an alternate history posts a block, this check will misfire

Copy link
Contributor Author

@mratsim mratsim May 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

process_block_header requires that the correct proposer was used:

https://github.com/status-im/nim-beacon-chain/blob/96ba039648e030f9e3725e71ac9dda34a02df657/beacon_chain/spec/state_transition_block.nim#L49-L70

So what can happen is:

  • (a) You found a block at that exact slot in the blockpool so it was run through process_block_header and you can attest to it as it was chacked to be from the expected proposer
  • (b) You didn't find a block at that exact slot in the blockpool so you vote for one of the head you have but the blck.slot is different from the current slot.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mm.. ok - so it's only because it's used on the head block that the function lives up to its name - I wonder if it wouldn't be more simple to just have the slot comparison with a comment that we're waiting for the the proposed block of that particular slot.

timeout = cutoffFromNow

if cutoffFromNow.inFuture:
let foundBlockInTime = await withTimeout(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what cancels the poll loop on timeout?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not clear on how to implement timeout with Chronos:

It contains a poll() so Chronos can do maintenance there, like stopping to yield the closure iterator, but in my testing the node gets stuck. Pointer appreciated:

https://github.com/status-im/nim-beacon-chain/blob/96ba039648e030f9e3725e71ac9dda34a02df657/beacon_chain/validator_duties.nim#L426-L443

Otherwise I can use an AsyncChannel but I would be surprised if there wasn't a simple solution, cc @cheatfate

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes but who the proposer is depends on which history you're following - isn't this "shortcut" only for when the proposer is from the same history as you?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was this supposed to be here? #1014 (comment), is this unclear or did I miss something?

@mratsim mratsim force-pushed the fix-attestation-signing-schedule branch from 96ba039 to ca2a08e Compare May 14, 2020 10:10
@mratsim mratsim force-pushed the fix-attestation-signing-schedule branch from ca2a08e to afd1650 Compare May 14, 2020 19:14
timedOut.store(false, moRelaxed)
let timeOutNotifChannel = timedOut.addr

proc waitForProposedBlock(node: BeaconNode, slot: Slot, timeOutNotifChannel: ptr Atomic[bool]): Future[void] {.async.} =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AsyncEvent that fires on updateHead is likely what you're looking for here - ping @cheatfate - no need for this polling

@mratsim mratsim added the 🕤 Postponed Not scheduled for the current sprint label May 15, 2020
@@ -170,6 +170,10 @@ type

slot*: Slot # TODO could calculate this by walking to root, but..

# Cache for ProtoArray fork-choice
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something I forgot until we talked about it in the other PR: BlockRef is not the right granularity for these checkpoints: epoch - that means you need to attach them to a (BlockRef, Slot) tuple, or BlockSlot, more simply, the issue being that epoch processing happens regardless if there's a block or not on the epoch boundary..

@arnetheduck
Copy link
Member

The codebase has changed significantly since this PR was made, and we're now closer to a principled solution to this - we can use #1700 to track the feature - closing PR as the code is no longer relevant, except as reference for a future implementation

@arnetheduck arnetheduck deleted the fix-attestation-signing-schedule branch November 11, 2020 07:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🕤 Postponed Not scheduled for the current sprint merge ready
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants