The goal stated again
The performance of Spacemesh network decreases with the number of nodes. On one hand we want to encourage decentralization, so we want many miners. On the other hard we want the network to perform smoothly.
The expected but unwanted phenomenon is “miner id splitting”. That is - a single entity (person, organization), given certain storage resources, splits their storage to smaller pieces and so establishes many independent miner identities. This is legal but will cause degradation of performance.
We seek for a simple yet effective solution to discourage splitting behaviour. Our primary hope is to adjust rewards algorithm so that a suitable economical incentive would emerge, counter-acting the splitting.
Simplified model of rewards
For the general discussion of possible solutions I will use a simplification of our current rewards model (which is nevertheless detailed enough for the purpose):
- for any given epoch
e
there is a number R(e)
(it is not crucial how this number is calculated).
- for a miner with absolute weight
w
in epoch e
, its expected total reward in this epoch will be R(e) * w
In other words: per-epoch reward is proportional to the absolute weight.
Let’s say Alice has storage resources so to establish a single miner with weight x
. Or, she can split her resources so to establish two miners with weights x/2
each. Her expected rewards will be:
- non-splitting:
x * R(e)
- splitting:
2 * (x/2 * R(e))
So, in this rewards model there is no difference. Splitting Alice gets the same reward as non-splitting Alice.
Fixed ATX cost model
The solution suggested by @iddo is based on a simple idea: we should charge every miner participating in an epoch for the pleasure to become the member of this epoch. In other words, this means charging for every ATX.
In the very simple variant (proposed for Genesis), this value to be charged per-ATX is just hardcoded as a protocol constant C. Then the example with Splitting Alice looks like this (and I am ignoring here the leftover re-distribution, which is a cosmetic detail):
- non-splitting:
x * R(e) - C
- splitting:
2 * (x/2 * R(e) - C)
So, the reward is decreased in the splitting case. This is what we wanted.
Problem #1: Gas cost
Guessing a “good” value of the constant C
is rather problematic. We would rather prefer to express C
as D * block_gas_price
, where D
is some protocol-constant denoting a number of gas units we want to charge for each ATX (this one will never change), and block_gas_price
we calculate separately per-block (so it will evolve with the changing market of gas prices). The problem here is that is is not easy to find a safe way to establish the per-block gas price (we already had one long discussion on this, no success yet).
Problem #2: Non-proportional incentive
Generally, economical incentives are efficient only if they are proportional to “wealth”. This is true in real life so probably also true for blockchains (and in our case miner’s absolute weight is a good measure of wealth). By splitting into two halves Alice gets a penalty of C
, which may be just negligible relative to her weight (i.e. to her per-epoch rewards). So effectively with this algorithm our non-splitting pressure is much higher towards small miners, but not so much towards whales.
Caution: Which may be good if we WANT this ! But if we rather want a similar pressure to everyone, this solution does not work well. My intuition here is that a non-proportional incentive will not work well over time.
Problem #3: The “real” cost of adding yet another ATX is not linear
One could argue that this “fixed ATX cost” algorithm sounds optimal because it maps nicely to technological reality. However, I claim that adding yet another ATX causes possibly some overflows and capacity issues which I doubt are linear. They might be linear when the network is small, but eventually some limits will be reached.
Proportional incentive via weights scaling
Sketchy idea
Let’s assume we were able to find some nice function f: ℝ -> ℝ
that we will use for scaling absolute weights of miners, and this scaling will be ONLY for the purpose of rewards calculation. If we want the Alice example to work well, the property we desire is that after splitting into two halves, Alice will experience a fixed proportional loss of her rewards. When expressed relative to her weight, this loss should be a fixed value. We just want a simple rule of thumb: something like “when you split to two halves, your rewards go down by 1%”.
Let’s do the math
In the non-splitting case she has the weight x
, so he earns the reward following this formula: R * f(x)
In the splitting case she has two miners, each having weight x/2
, hence she earns two rewards (one for each miner) following this formula: R * f(x/2)
.
We want to introduce a protocol constant Θ
representing the proportional loss. Say, if Θ = 0.01
then splitting into two halves should cause your rewards to be only (1-Θ)
fraction of non-splitting rewards. So, with Θ = 0.01
you will lose 1% of your rewards by splitting your miner into two halves.
This rule leads to the following equation:
R(e) * f(x/2) * 2 = (1-Θ) * R(e) * f(x)
In the above equation, unknown is the function f
. This equation can be solved and the family of solutions is (A - arbitrary non-zero constant):
f(x) = A * x^p
, where p=1-log(1-Θ)/log(2)
Because any value A
does the job, we may take A=1
.
Conclusion
Weights scaling function:
f(x) = A * x^p
, where p=1-log(1-Θ)/log(2)
… forms a proportional anti-splitting incentive, that is independent of gas price. This incentive is possibly a better solution than the “fixed ATX cost” because it avoids all problems of the other solution.
In this solution, the value Θ
is a protocol constant and should be sealed into the blockchain at Mainnet launch. I suggest the value Θ = 0.01
.
In the table below there are some example values of Θ
and the corresponding exponents p
:
Θ | p
--------------------------------------
0.005 | 1.0072315692310758
0.010 | 1.0144995696951151
0.020 | 1.0291463456595165
0.030 | 1.043943347587597