Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Proposer priority value is not carried over after round skips #3044
We are seeing proposers being reselected for a few blocks in a row in the
Here is what we were able to see:
This looks like that in rounds > 0 the proposer priority is not decremented for the actual proposer. This is most likely a bug in the proposer selection.
What is actually happening is:
Block 1 R0: Val C: round skip <- prio decremented
Block 2 R0: Val B: round skip <- prio decremented
Block 3 R0: Val C: propose <- prio decremented
I would expect the following:
Block 1 R0: Val C: round skip <- prio decremented
Block 2 R1: Val D: propose <- prio decremented
This is working as designed, for round incrementAccums to not carry over into the next height. And, the proposer for (H,R) is the same as (H+1,R-1) in the absence of validator set changes.
The main problem with any round data carrying over is that there actually isn't a canonical round for a commit until it is agreed upon by inserting it into the blockchain. So, a commit might happen at (H,R), but it's possible that the other validators didn't see (H,R) but rather only a commit at (H,R+1) and so on. What's guaranteed by safety is that the decided block will be the same (given assumptions about the number of byzantine validators), not that everyone agrees on which round it happened.
So carrying over rounds potentially introduces an additional degree of freedom for exploitation by a chain of proposers. Comparatively, the current proposer algorithm is more deterministic. It's probably worth considering alternative implementations for a public blockchain setting, though I'm not sure what would be simplest. It may get exploited for GoS but it doesn't seem like a pressing issue for mainnet just yet. Lets consider many alternatives and pick the simplest alternative, it looks like the solution space is large.
for round incrementAccums to not carry over into the next height. OK.
Then, doesn't the priority still should decrease by number of proposed blocks multiplied by total power somewhere after that?
Fair proposing logics should possess the rule that at any given circumstances, every proposing of a block should result in decreasing priority by total-power no matter reason behind.
If the logic should choose straight consecutive proposer, it is fine. However current sdk is lack of appropriate priority decreasing process existence.
Or, if the consecutive proposings are not punished by decreasing priority, the proposings should not result in proposer bonus rewards too. Two of them should always be together.
I agree as well Zaki. I don't see a clear way to prove that a deterministic proposer election has the properties we want (#2890) whereas its fairly trivial with randomness. (I see two possibilities VRF from sometime in the last blocks, or VDFs. VRF's are quite well understood, so may not be too far out)
I think we have option now the looking the proposer of the block when we apply changes and rotate the validator pool until we rotate pass the proposer once.
I think your right @zmanian (Though it doesn't actually need the proposer address, it just needs the round number in the header)
I also agree that this may not be a huge problem for mainnet, but my sense of how using round number appearing in the header is as follows (I also think its what @zmanian is implying, thought it would be useful to write below for concreteness):
The hash of the block committed (which everyone is voting on) depends on the block header. The block header contains the round number.
Once a validator sees enough precommits to be a commit in the round which they are at, they would calculate a 'candidate-next-proposer' and see if it is themself. If so, propose the next block. Everyone else upon receiving the 'next block' would then learn which the round the prior commit was in (as that is in the block header), and can consequently verify the current proposer is correct. This should give us sufficient flexibility to decrement proposer priorities as we so choose for rounds
The DOS potential does increase now, as when you receive the newly proposed block's header, you first have to parse its round, then derive the correct proposer, and see if it matches. Whereas previously figuring out the correct proposer for the subsequent block was super easy, since it was round-independent. This cost should be fairly cheap by just caching the
Is the above right, and is the additional cost sufficiently cheap for us to implement? Lite clients would also have to do this sort of replay to determine the proposer priorities based off of the round, but this is a trivial amount of computation as compared to signature verification. (I definitely think its a #postlaunch thing to do though. I'd also suggest only decrementing the proposer, what hendrik was originally suggesting as well)
added a commit
Dec 20, 2018
This patch would be the following:
Block 1 R0: Val C: round skip <- prio decremented (with slashFactor decreased)
Block 2 R0: Val A: propose <- prio decremented
AND NEXT VALIDATOR ROUND WOULD BE:
Block 1xx R0: Val C: round skip <- prio decremented (with slashFactor decreased)
Block 1xx+1 R0: Val Z: propose <- prio decremented
AND Z WOULD BE different every VALIDATOR ROUND
is this workable?