stuffy stuff
This commit is contained in:
parent
679b7a27a6
commit
15f5f10038
9 changed files with 1084 additions and 59 deletions
433
public/writings/how-much-hashrate-does-a-fork-chain-need.html
Normal file
433
public/writings/how-much-hashrate-does-a-fork-chain-need.html
Normal file
|
|
@ -0,0 +1,433 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Pablo here</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="stylesheet" href="../styles.css" />
|
||||
<style>
|
||||
table.numbers {
|
||||
border-collapse: collapse;
|
||||
margin: 16px auto;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
table.numbers th,
|
||||
table.numbers td {
|
||||
padding: 4px 12px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table.numbers th {
|
||||
border-bottom: 2px solid #000;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main>
|
||||
<h1>Hi, Pablo here</h1>
|
||||
<p><a href="../index.html">back to home</a></p>
|
||||
<hr />
|
||||
<section>
|
||||
<h2>How much hashrate does a fork chain need?</h2>
|
||||
<p><em>Published: 2026-10-25</em></p>
|
||||
|
||||
<p>
|
||||
Ever since the BIP-110 chain failed, a few concerns have been bouncing around in my head (to be clear, they have
|
||||
nothing to do with the ideas behind BIP-110). What caught my attention was how it
|
||||
failed, and what that says about the power miners hold over Bitcoin now.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This post is the current state of my thinking. It is work in progress, and I'd love to be told where I'm wrong.
|
||||
</p>
|
||||
|
||||
<h3>BIP-110 tried and died</h3>
|
||||
|
||||
<p>
|
||||
When BIP-110 split off, its chain got so little hashrate that not even the fanatics stayed for
|
||||
long. It mined 8 blocks and was definitively abandoned within 20 days. On the first day, poolcoin
|
||||
(I'll call "normal" Bitcoin that for fun) already got ahead significantly. By day 3 it was pretty much a closed
|
||||
case.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The interesting part is that this behaviour was very decoupled from the social acceptance of BIP-110. BIP-110
|
||||
was far from any majority of proactive support, but I personally estimate somewhere around 5-20% of the network
|
||||
was supportive of it, and the rest was mostly neutral. But its brutal death after the chainsplit was not
|
||||
reflective of this. Why didn't all the fanatics stick around? Because there was no shortage of them. We know
|
||||
because now they've all moved on to Blakecoin. Those guys were willing to run BIP-110 to the ultimate
|
||||
consequence of splitting from the world, but still, they left the BIP-110 chain. Why? Because the chain was
|
||||
simply unusable:
|
||||
</p>
|
||||
<ul>
|
||||
<li>blocks took days to arrive, not minutes, and</li>
|
||||
<li>the difficulty adjustment that could have fixed that sat years in the future.</li>
|
||||
</ul>
|
||||
|
||||
<p>Believers walked away from the chain they believed in, because using it was impossible.</p>
|
||||
|
||||
<h3>What actually concerns me</h3>
|
||||
|
||||
<p>
|
||||
That episode made something concrete for me: hashrate is decoupled from nodes and users, and
|
||||
hashrate (or the lack of it) can be used to make a chain unusable, whatever its users think of it
|
||||
ideologically/politically.
|
||||
</p>
|
||||
|
||||
<p>Put that together and you get a loop:</p>
|
||||
<ol>
|
||||
<li>Low hashrate → long blocktimes, and a long wait for the difficulty adjustment.</li>
|
||||
<li>Long blocktimes → the chain is too slow to transact on.</li>
|
||||
<li>Too slow to transact → users who hold and depend on bitcoin leave the chain.</li>
|
||||
<li>Fewer users → less reason to mine it → even less hashrate.</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
Mining is heavily centralized in a handful of pools. That means a mining cartel could trigger this loop on any
|
||||
chain it chooses to starve.
|
||||
</p>
|
||||
|
||||
<p>So I set out to answer some questions with numbers:</p>
|
||||
<ol>
|
||||
<li>
|
||||
In a chainsplit, how does a chain's share of hashrate affect the experience of the people
|
||||
using it? What counts as "too little" hashrate, and what counts as "too long" a blocktime?
|
||||
</li>
|
||||
<li>
|
||||
Given today's mining pool concentration, which combinations of pools have the power to keep
|
||||
a fork chain alive, or to kill one?
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<h3>Why a minority chain is so slow</h3>
|
||||
|
||||
<p>
|
||||
When a chain splits, both sides keep the difficulty they had at the moment of the split. Suppose one side ends
|
||||
up with a share <code>h</code> of the hashrate. Then:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Blocks arrive <code>1/h</code> times slower. Half the hashrate means 20-minute blocks; a tenth means
|
||||
100-minute blocks.
|
||||
</li>
|
||||
<li>
|
||||
It stays that slow until you mine 2016 blocks, the next adjustment. At <code>1/h</code> the usual speed, that
|
||||
takes <code>14/h</code> days instead of the usual two weeks.
|
||||
</li>
|
||||
<li>
|
||||
Even then, relief is partial: each adjustment can cut difficulty by at most 4×. A very weak
|
||||
chain needs several adjustments, each one arriving sooner than the last, before it is back to 10 minutes.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Here is what that looks like:</p>
|
||||
<table class="numbers">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Hashrate</th>
|
||||
<th>Time between blocks</th>
|
||||
<th>First adjustment</th>
|
||||
<th>Back to 10 min</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>50%</td>
|
||||
<td>20 min</td>
|
||||
<td>28 days</td>
|
||||
<td>28 days</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>25%</td>
|
||||
<td>40 min</td>
|
||||
<td>56 days</td>
|
||||
<td>56 days</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>10%</td>
|
||||
<td>1.7 hours</td>
|
||||
<td>140 days</td>
|
||||
<td>175 days</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5%</td>
|
||||
<td>3.3 hours</td>
|
||||
<td>280 days</td>
|
||||
<td>1.0 years</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1%</td>
|
||||
<td>16.7 hours</td>
|
||||
<td>3.8 years</td>
|
||||
<td>5.1 years</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<figure style="width: 97.5%; margin: 10px auto;">
|
||||
<img width="100%" height="auto" src="../static/chainsplit-blocktimes.png"
|
||||
alt="Blocktimes grow as hashrate shrinks">
|
||||
<figcaption>Blocktimes grow as hashrate shrinks</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>
|
||||
The second column is what hurts, and the third is for how long it's going to hurt. Things become worse given
|
||||
the importance of expectations: if users think a chain won't be usable in the future, even if it's barely
|
||||
usable now, they will drop it anyways due to expectations, which triggers a doom loop.
|
||||
</p>
|
||||
|
||||
<h3>Who uses the chain, and how long will they wait?</h3>
|
||||
|
||||
<p>
|
||||
"Usable" means different things to different people, so I modelled three personas, each with a tolerance for
|
||||
how long they're willing to wait for a transaction to reach 3 confirmations, which for
|
||||
simplicity we will define as settled.
|
||||
</p>
|
||||
<table class="numbers">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Persona</th>
|
||||
<th>Who they are</th>
|
||||
<th>Will wait for 3 confirmations</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Hodler</td>
|
||||
<td>Holds, rarely moves coins</td>
|
||||
<td>1 week</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Medium of exchange</td>
|
||||
<td>Pays and gets paid</td>
|
||||
<td>1 day</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Institution</td>
|
||||
<td>Settles business on a schedule</td>
|
||||
<td>3 hours</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
Since block arrival is random, a wait isn't a single number but a distribution. Sometimes you get lucky,
|
||||
sometimes you don't. I settle that with a service level: at p90, 90% of a
|
||||
persona's transactions must reach 3 confirmations within its tolerance. On the regular 10 min schedule, that p90
|
||||
wait is about 53 minutes (read as: 90% of times, you will see three blocks confirmed in under
|
||||
53 min).
|
||||
</p>
|
||||
|
||||
<h4>Assumptions</h4>
|
||||
|
||||
<p>To keep this tractable, I assume:</p>
|
||||
<ul>
|
||||
<li>3 confirmations count as final.</li>
|
||||
<li>Static hashrate: each side keeps its share of hashrate for good.</li>
|
||||
<li>
|
||||
Empty mempool: no fee competition, no queueing. This is the best case scenario: if you start
|
||||
facing a clogged mempool, waits would be even longer for some.
|
||||
</li>
|
||||
<li>
|
||||
The split starts at the beginning of a difficulty period, so the minority chain has a full
|
||||
2016 blocks to grind through before any relief. Note that changing this can greatly influence the delay to the
|
||||
first difficulty adjustment, but I won't explore this further since for now it seems canonical that fork
|
||||
activations happen on the start of difficulty periods.
|
||||
</li>
|
||||
<li>
|
||||
Out of scope: introducing the effects of hard forks of any kind, or more generally anything
|
||||
that tampers with the difficulty adjustment.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>The numbers</h3>
|
||||
|
||||
<p>
|
||||
Turning tolerances into hashrate is simple division. If a persona tolerates waits <code>k</code> times longer
|
||||
than mainnet's, the chain can be <code>k</code> times slower, so it needs <code>1/k</code> of the hashrate. This
|
||||
is the share of total hashrate a chain needs to keep each persona on it:
|
||||
</p>
|
||||
<table class="numbers">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Persona</th>
|
||||
<th>Tolerance</th>
|
||||
<th>p50</th>
|
||||
<th>p90</th>
|
||||
<th>p95</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Institution</td>
|
||||
<td>3 hours</td>
|
||||
<td>14.86%</td>
|
||||
<td>29.57%</td>
|
||||
<td>34.98%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Medium of exchange</td>
|
||||
<td>1 day</td>
|
||||
<td>1.86%</td>
|
||||
<td>3.70%</td>
|
||||
<td>4.37%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Hodler</td>
|
||||
<td>1 week</td>
|
||||
<td>0.27%</td>
|
||||
<td>0.53%</td>
|
||||
<td>0.62%</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
Institutions are demanding: a chain needs roughly 30% of all hashrate before they'll use it. Everyday spenders
|
||||
need under 4%, and hodlers need about half a percent.
|
||||
</p>
|
||||
|
||||
<h4>Defensive coalitions: who can keep a fork chain alive?</h4>
|
||||
|
||||
<p>
|
||||
Now map those bars onto today's mining pools. If a group of pools wants to keep a minority chain usable, how
|
||||
many does it take?
|
||||
</p>
|
||||
<table class="numbers">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Persona</th>
|
||||
<th>Needs</th>
|
||||
<th>Smallest coalition today</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Institution</td>
|
||||
<td>29.57%</td>
|
||||
<td>2 pools (e.g. Foundry USA + AntPool)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Medium of exchange</td>
|
||||
<td>3.70%</td>
|
||||
<td>1 pool (any of the top 7)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Hodler</td>
|
||||
<td>0.53%</td>
|
||||
<td>1 pool (any of the top 14)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
A single mid-sized pool committing to a chain is enough to keep it usable for hodlers and everyday spenders. A
|
||||
couple make it workable even for the hypothetical institutions.
|
||||
</p>
|
||||
|
||||
<h4>Offensive coalitions: who can force users onto a softfork?</h4>
|
||||
|
||||
<p>Now flip it around, because this is the scenario that worries me.</p>
|
||||
|
||||
<p>
|
||||
A coalition of pools activates a softfork that users don't want. The users reject it and stay
|
||||
on the chain without it, or even push for a URSF. That chain is left with whatever hashrate the coalition didn't
|
||||
take. If that falls below the users' bar, the chain they want becomes unusable by their own standards, and
|
||||
they're forced to either jump across to the cartel softfork, or hardfork away like the Blake boys did.
|
||||
</p>
|
||||
<table class="numbers">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Persona</th>
|
||||
<th>Softfork side must hold</th>
|
||||
<th>Smallest coalition today</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Institution</td>
|
||||
<td>over 70.43%</td>
|
||||
<td>4 pools (the top four, 72.34%)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Medium of exchange</td>
|
||||
<td>over 96.30%</td>
|
||||
<td>11 of 18 pools</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Hodler</td>
|
||||
<td>over 99.47%</td>
|
||||
<td>14 of 18 pools</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<figure style="width: 97.5%; margin: 10px auto;">
|
||||
<img width="100%" height="auto" src="../static/chainsplit-coalitions.png" alt="Pool coalitions">
|
||||
<figcaption>Pool coalitions</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>
|
||||
If you consider AntPool to actually be AntPool and friends, then you only need the three top pools today to bend
|
||||
institutions into a softfork, which you could argue already creates enough gravity across miners and users that
|
||||
everyone will end up in the softfork chain.
|
||||
</p>
|
||||
|
||||
<h3>The scenario that scares me</h3>
|
||||
|
||||
<p>Here's the nightmare, using the numbers above:</p>
|
||||
<ul>
|
||||
<li>
|
||||
Foundry, AntPool & friends, and F2Pool, about 72% of hashrate between them, sponsor a softfork that sets
|
||||
the minimum fee to 5 sat/vB.
|
||||
</li>
|
||||
<li>
|
||||
They go hard on propaganda: "stand aside, lady, it's for the security and future of the network."
|
||||
</li>
|
||||
<li>They set a short deadline that barely gives the community time to react, say four weeks.</li>
|
||||
<li>
|
||||
The rest of the network doesn't want this. But the rest of the network doesn't have the hashrate to keep a
|
||||
user-activated chain usable, at least not for anyone who needs transactions to settle within hours.
|
||||
</li>
|
||||
<li>
|
||||
For most users, paying 5 sat/vB is a lesser evil than risking the run-for-your-life scenario of jumping into a
|
||||
hard fork (to make matters worse... which one?). And staying in the "old" chain is not feasible since it will
|
||||
die starved of hashrate.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Nothing in that scenario requires breaking Bitcoin's rules. It only takes a few pools agreeing with each other,
|
||||
and the loop from the start of this post does the rest. It's a fuck up in Bitcoin's design, and as far as my
|
||||
knowledge goes, it's been here since the chain got started. We're just starting to see it emerge now.
|
||||
</p>
|
||||
|
||||
<h3>The solution</h3>
|
||||
|
||||
<p>
|
||||
I have no solution for this. It somehow feels all the forces are pointed at making this worse. The only "happy
|
||||
scenario" is Bitcoin gets slowly destroyed like email did, we lose all the usefulness it was giving us, and
|
||||
we're back at square one. The community with the ethos (supply capped, permissionless, decentralized freedom
|
||||
money) needs to start from scratch with some new coin/solution, with all the challenges that come with it. We
|
||||
could be locked in fiat hell for decades before we pull it off.
|
||||
</p>
|
||||
|
||||
<p>Or perhaps the Blake boys will somehow make it. I have little faith but I wish them the best.</p>
|
||||
|
||||
<h3>Code</h3>
|
||||
|
||||
<p>
|
||||
You can find the repo where I worked this out <a href="../static/hashwars-musings.zip">here</a>.
|
||||
</p>
|
||||
|
||||
<hr />
|
||||
<p><a href="../index.html">back to home</a></p>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue