A Deterministic Tiebreaker for Bitcoin Block Selection: Enhancing Fairness and Convergence

Am I a mathematical idiot, or isn’t half of 2^256 actually 2^255, not 2^128?

Edit: ie you’re essentially coinflipping the first bit in a 256 bit string as either 1 or 0.

Edit 2: Other than that, my first instinct is this is an excellent idea. Simple & effective.

3 Likes

Lol yeah, brain fart, I’ll add the fix

2 Likes

Why not just take the lower of the two hashes (if interpreted as a 256-bit integer)? Surely that’s always deterministic and has nothing to do with bandwidth/latency.

EDIT:

Also bonus: Technically picking the lower hash is fairer since the lower-hash miner has put in “more PoW” (even if it’s only slightly more) since there are potentially more consecutive 0-bits in the high order bit positions.

Or are you worried that using the lower hash does indeed enable some selfish mining tricks because if they throw more PoW at it than their peers they can pull it off?

What if the lower hash is lower by a significant threshold?

Meh.

In that case a miner who gets a “lucky” hash would know it’s definitely a lucky hash and could withhold it until a block is found and THEN release it, so to make everyone waste work and give himself comparative advantage.

With H(A||B) he can’t know whether his hash will be lucky, because B will be unknown and it will have 50:50 of flipping his block.

5 Likes

Hmm. Yes correct.

I guess if they define some threshold when they feel “lucky enough” (say has 2, 3 or 5 or whatever extra preceding 0-bits)… then they can do the selfish mine, otherwise mine normally. Yeah, good point.

1 Like

OK, I have read the spec 3 times now, I think I can say I understand it at this point.

  • The idea will just work like described, once all/most miners update the software :white_check_mark:
  • It’s easy to code :white_check_mark:
  • I see no significant downsides right now :white_check_mark:
  • It is beneficial to the network :white_check_mark:
  • Makes mining more fair for everybody :white_check_mark:

I think we should implement this ASAP. I wonder how it is we didn’t do it earlier, seems like a total no-brainer to have it.

I guess maybe before people did not care about small percentage of forks caused by worse connectivity?

2 Likes

Based on my telegram message:

The first seen idea combined with headers first means that miners switch mining to a new block in less than 100ms for most. (this is a speed of light thing, as that is the speed of electrons-reactions. If you want help with the math, ask grok: https://x.com/i/grok/share/fOxbygzh92j680tA02N0oyg7Z)
Which effectively means that the problem being “solved” does not exist.

On the other hand, a block that can be mined which will replace an already mined one misaligns the incentives. A miner can suddenly choose to continue mining on a tip-minus-one (in order to hurt another miner or whatever) instead of mining on the tip, with little to no risk.

So, yeah, the downside to this is that it opens up to unknown unknowns while it doesn’t actually solve a real world problem.

Looks very promising. At first and second glance, this looks like an oversight that could’ve been done long ago! Not to say I’m not missing something, but definitely interesting.

I don’t know, it needs more analysis, no rush, we don’t have the problem which this would hypothetically solve.

How I got here is asking myself: “Why are orphan rates a problem?” and “How high orphan rates could we tolerate?” but that’s for another topic, the takeaway from my pondering is this: if everyone had equal orphan rates then they wouldn’t be a problem at all.
That’s how I got here, wondered “If we have to have some orphans then what if there was a way to equalize orphan rates across pools?”

Uncle merging proposals like Tailstorm would address the problem by subsidizing orphans, and
this proposal would address the problem socializing orphan losses.

Header-first requires mining an empty block to get the subsidy. How would header-first work when fees take over?
But still, if bandwidth significantly outpaces our network growth and demand for transactions then it may as well be that we never see orphan rates become big enough to be a problem, so changes to 1st seen would be unnecessary.

The current state of things is that miners are free to implement whatever tie breaker policy they want because any 2 tips are equal as far as consensus is concerned, favoring either is subjective.
That means we can actually have competing policies, there needs not be consensus on this policy.

With the H(A||B) as policy we’d have an objective tie-breaker for the case when chainworks are equal.


Something more to ponder, what if longer tips are competing, e.g.:

N+A+B vs N+C+D

should we evaluate H(B||D) or H(A||C) to pick the tip? or some 3rd thing like H(A||B||C||D)?

what if evaluating N+A+B+C vs N+D+E+F ?

in that case difficulty in C and F could differ so our DAA may resolve the conflict because one of the chains would have higher chainwork?

It would work exactly the same.
The question asks a question that is irrelevant to the reason miners use header first mining.

The miners essentially have a hardware problem.
The moment a block-header comes in, they don’t have anything to mine. So they can just turn off the mining hardware and save power that way. That is the “proper” solution. Don’t spend money on power.

The hardware problem is that this turning off and then 2 or 10 seconds later turning it on again is really bad for your mining hardware. Imagine going from zero ampere usage to 100 ampere in milliseconds. That will just create massive power (voltage) fluctuations that make your hardware reboot or worse.
In other words, they can’t turn off their hardware.

So, what to do?

  1. you keep mining the block you already started mining. This may create an orphan, though. But they are rare, so that’s a risk.
  2. you mine on top of the chain that you have validated as having the most PoW, with an empty block until you have new transactions to put into it.

Most miners pick 2.

Work? Sure, you extend a header with your empty block and get paid 0 for it (or in nearer future: just 0.1 BCH while everyone else is getting 1 BCH for blocks filled with TXs).

The longer you have to wait to get the full block, the longer you delay producing a template with 1 BCH reward and getting to work on it, and the longer you work on a template with just 0.1 BCH reward. Your costs are the same, but for some % of the time you revenue will be 10% of what it could be.

This reduces your average revenue per block (but cost stays the same), and your margins suffer. As you say, the “proper” solution is to avoid it by simply not mining until you verify the tip and fill your template to 1 BCH, then you preserve your margin - and as you say, that’s technically not possible to do with 0 lag, due to hardware limits.

One mining company claims a 15s cycle (5s to drop, 10s to ramp up again):

If tech gets better and gap between subsidy and fees grows, wouldn’t miners start dropping header first mining to optimize their margins?

Does the solution not incentivize selfish mining strategies?

Currently: Receiving a block means I have incentives to switch to it immediately. If I don’t and I find a competing block later, nobody else is switching to me, and my competing tip is disadvantaged for 100% of mining powers that is not me.

Under a deterministic scheme: I can just mine the previous tip at my leisure. If I find a competing block, I can release it and get 50% of the miners who are not me to switch - which combined with myself means I get >51%!

If a second block arrived before my competing tip, that would mean my own competing tip hasn’t been found, so I didn’t lose anything. The only scenario in which I lose is if the second block arrives at the same time or just a little after my competing block.

What’s the advantage of doing this? Punishing people for not being in my pool, per selfish mining. If a small miner is not in my pool, he will always risk losing a tip to me this way, which is significant. If he caves and joins me, he only has a minute risk described in the above paragraph.

This worsens the more hashpower I have. There’s probably some math to be worked out, but I doubt the catastrophic risk of incentivizing lots of big pools to straight up not mine on the public tip is worth the improvement.

I think the biggest flaw with these schemes is there’s no way to distinguish between a block genuinely delayed by latency, and a block that’s deliberately mined later.

1 Like

That’s not how it works. Either they all (except the miner of the competing block) switch or nobody does, and you don’t know until you mine it - because it will depend on H(A||B).

Alright, that still works out to expected 50% switching over time, which is more than 0% per status quo.

Yeah but it also works out to 50% of the honest block reward payout.

  1. Honest: you have 10% hash and 10% chance of getting paid 1 block reward.
  2. Selfish: you have 10% hash and 5% chance of getting paid 1 block reward.

PS check out some discussion I had with zawy: https://github.com/zawy12/difficulty-algorithms/issues/76#issuecomment-2798012615

Not exactly, if I am honest and just publish my blocks right away, I always run the risk of not getting paid for the block I just published regardless of latency.

Status quo honest: I have 10% hash and (10% - S^2 - L) chance of getting paid.

S is the risk of the selfish miner getting two blocks in a row to reorg. Rises with more selfish hashpower
L is some latency related chance of my block getting outcompeted by another honest miners. Rises with worse latency and shorter blocktime

Determinstic honest: I have 10% hash and (10% - S/2) chance of getting paid.

S/2 is the risk of selfish miner getting one competing block and the block hashes to reorg, signified by the “/2”.

Under most circumstances you’d expect S/2 > (S^2 + L), no?

Not quite, because a competing block doesn’t exist. If you publish immediately, all honest hash switches to you. If some hash is lagging, it could mine a competitor and have 50% of flipping you. But from your PoV chances of losing an immediately published block is given by (%hash that lags x lag/10min)*50%, not just 50%.

Uh did you not read the rest of my post

sorry, you caught me at an awkward time with this and I had limited attention :sweat_smile:

I think the correct is:

(10% - S^2 - L) vs (10% - S^2 - L/2)

It is literally socialization of orphan losses. Of course if it’s your block in question you will ignore the scheme and still try to get that +1 for your block. But if you have no skin in the game, you treat public tips with the H() tie-breaker.

Let’s go through some scenarios:

  • You mined a block first. After 2s someone else mined a competitor (due to latency). You still try to mine +1 on top of your block, but the whole rest of the network will either favor yours or the competitor, 50:50. Sometimes you win, sometimes he wins: here you socialize orphan losses with the less-connected miner - but the other participating miners actually enforce this. They have no skin in the game, they don’t care whether you or the competitor wins.
  • You thought you mined a block first, but a selfish miner already had a secret block. Now that your block is public, does he release it or not? Depends on the hash. If he wins: he releases it immediately. If he loses, he tries for +1. But rest of the network including you will be trying for +1 on your honest tip. Who wins? If the selfish miner had just released his block as soon as he had it, he wouldn’t be in this situation, he’d just get paid normally.