There has been a lot of discussion surrounding dynamic plasma lately, and different ideas have been presented by community members. I’ve spent some time researching the topic and I’ve attempted to combine some ideas in this post and present some ideas for a dynamic plasma implementation.
I didn’t post this in the dynamic plasma thread, since I wanted to create a thread that focuses mainly on the pros/cons of the ideas presented in this post.
Background
Why do we need dynamic plasma
Currently our network has a hardcoded throughput limit of 100 account blocks per momentum. For an account block to be eligible for inclusion in a momentum, the account block has to have a minimum amount of plasma committed to it. This minimum amount of plasma needed is dependent on the type of the transaction. For example, calling an embedded contract requires a higher plasma commitment than a normal send transaction.
Since our network utilization rate is so low right now, this mechanism works without issues. There is always space in the momentum so users do not need to compete for their account block to get included in the next momentum.
Once the network utilization rate picks up, we will start running into problems. Since a momentum can fit a finite number of account blocks, there has to be a mechanism that allows users to compete for inclusion in a momentum.
What is plasma
The founding team introduced plasma as “an anti-spam mechanism that acts as the network gas” and “as a third dimension asset similar to the mana concept employed by many popular games”.
Based on this and based on the current implementation of plasma, we can come to the conclusion that plasma has three purposes: mitigating spam, representing a computational cost for transactions, and allowing for transactions to be prioritized (competing for inclusion in a momentum).
The current implementation only fulfills one of these purposes: representing a computational cost associated with a transaction. The anti-spam properties of the current implementation are relatively weak and there is no mechanism that allows for users to compete for inclusion in a momentum.
Plasma as a representation of computational resources
Using “gas” to represent computational resources is a widely utilized concept in other blockchains such as Ethereum. Ethereum transactions require the user to commit a minimum amount of gas to the transaction in order for it to be eligible for inclusion in the next block. The minimum computational cost for a regular ETH transaction is 21,000 gas units. This amount of gas has to be committed to every transaction. The gas is paid for in ETH and the protocol burns this gas when the transaction is processed. This is only a theoretical minimum fee, since in practice the total fee for a transaction is more than this and fluctuates based on network usage.
The reasoning for why the requirement is 21,000 gas units can be found here. Based on Vitalik’s explanation we can see that the gas units required for a transaction are based on the actual computational resources that are needed to process the transaction.
In our network a regular transaction also has a computational cost of 21,000 gas units, or rather, plasma. Whether these computational requirements are based on actual testing and benchmarking or just on guesstimation is unknown. The computational cost differs depending on the transaction’s complexity. For example, calling an embedded contract to collect rewards has a computational cost of 73,500 plasma since it requires more computational resources to process the transaction.
The maximum account blocks allowed in a momentum is currently 100 and the amount of plasma the most expensive transaction requires is 105,000 (registering a pillar). Based on this we can calculate that the theoretical maximum computational units our network will currently process is 10,500,000 units per momentum.
Plasma as a transaction prioritization mechanism
As stated before, our network doesn’t have any transaction prioritization mechanism currently, but plasma can be used for this purpose, with the basic idea being that committing more plasma to the transaction means higher prioritization of the transaction.
Plasma as an anti-spam mechanism
The third purpose of plasma is to work as an anti-spam mechanism. To me, on-chain spam can be defined as any activity that floods the chain with transactions with the intention to significantly limit the ability of others to use the network. There can be many reasons for conducting a spam attack - for financial gain, for example.
The most common anti-spam mechanism used by networks is to require a transaction’s sender to pay a fee. The idea being that the cost of fees will be greater than the potential gain from an attack.
I think that the anti-spam properties of our current plasma implementation are limited, mainly because the rate at which plasma is currently “recharged”. It’s too fast to effectively throttle an account’s ability to send transactions.
Ideas for an initial dynamic plasma implementation
Below are some ideas for how to fulfill the goals presented above. Example implementations and pseudo-code examples of the following algorithms can be found here.
Goal 1: Computational resources
This goal is already partially met in the current plasma implementation. But since we have finite momentum space, we need to increase the cost of computational resources when demand increases.
To meet the goal, we could utilize a dynamic algorithm that adjusts the “price” of computational resources based on network utilization which is readjusted on every momentum.
The basic idea being that the readjustment algorithm targets half full momentums. This means that if the previous momentum was more than half full, the price of plasma increases. If the previous momentum was less than half full, the price of plasma decreases. If the momentum was exactly half full, then the price stays the same. For a transaction to be eligible for inclusion in the next momentum, the account block has to commit at least the base plasma requirement for the transaction multiplied by the minimum price of plasma, the “base price”.
Instead of the current per momentum transaction cap, we would have a per momentum base plasma cap, since different transactions require a different amount of base plasma as explained before.
The price of plasma will increase exponentially if there are momentums that are over half full consecutively, meaning that it is economically unviable for momentum size to stay high indefinitely.
Example:
Momentum Height | Momentum Fullness | Base Price | Price Change |
---|---|---|---|
1 | 50% | 1000 | 0% |
2 | 100% | 1000 | 0% |
3 | 100% | 1125 | 12.5% |
4 | 100% | 1265 | 12.5% |
5 | 100% | 1423 | 12.5% |
6 | 100% | 1600 | 12.5% |
7 | 100% | 1800 | 12.5% |
8 | 100% | 2025 | 12.5% |
The main benefit of targeting half full momentums, instead of full momentums, is that the base price for plasma is adjusted algorithmically, reducing the need for a bidding war among users when there is a short term spike in momentum space demand. It is also easier for wallets to predict the minimum plasma price needed for a transaction.
This is similar to how Ethereum’s current fee adjustment algorithm works as described in EIP-1559.
Goal 2: Transaction prioritization
Even with a dynamically adjusting base price for plasma, there still needs to be a way to prioritize transactions in the situation where the momentum cannot fit all the transactions that are eligible. This could be achieved by simply prioritizing account blocks based on the price of plasma used in the account block.
plasmaPrice = ab.UsedPlasma / ab.BasePlasma
To be eligible for inclusion the account block must fulfill: plasmaPrice >= momentum.BasePrice
This allows a user to commit more plasma to their transaction than what is needed, in order to have a better chance of being included in the next momentum if the network is congested.
Note 1: Account blocks sent by embedded contracts have endless plasma and should probably always have the highest priority, so this is something that has to be taken into account when determining the per momentum base plasma cap.
Note 2: Since we currently have no way of “forcing” pillars to order transactions in a specific order, there is no way to guarantee that pillars prioritize transactions as intended. I think the best that we can do right now, is minimize the incentives for pillars to alter the ordering of transactions.
Goal 3: Anti-spam
The anti-spam aspect of plasma is probably the trickiest goal to achieve, depending on what the requirements are. The dynamic adjustment algorithm presented in Goal 1 works as an anti-spam mechanism, but it is probably not enough on its own.
PoW Plasma anti-spam
Currently there is a hard coded PoW-to-Plasma conversion rate, meaning that a given amount of PoW will always be converted to a specific amount of plasma. Currently there is also a hard coded limit to how much PoW can be converted to plasma for an account block.
If account blocks are prioritized based on plasma, then having a hard coded limit to how much PoW plasma can be generated can make PoW transactions unviable when there’s high demand for momentum space.
But if the hard coded cap, for how much PoW plasma can be generated, is removed, then a user with a significant amount of computing power would be able to generate huge amounts of plasma and gain an undue amount of control over total network bandwidth.
To mitigate this problem, we could introduce a dynamic PoW-to-Plasma conversion rate (difficulty-per-plasma), that is dependent on network utilization and how much of the total plasma is being generated by PoW.
In the example algorithm a difficulty-per-plasma value is readjusted on every momentum. The target PoW plasma rate in a momentum is set to 20% - this means that when the momentum is over or equal to half full, the PoW plasma percent should be 20%. If it’s less than that, the difficulty-per-plasma will decrease, if it’s more than that, the value will increase. If the momentum is less than half full, the PoW plasma target is 100%, meaning that the PoW plasma percent can be 100% of the momentum without penalty.
The example algorithm’s output when PoW plasma is 100% of the momentum’s plasma and the momentum is equal to or over half full:
Momentum Height | Momentum Fullness | PoW plasma | Difficulty-per-plasma | Difficulty-per-plasma change |
---|---|---|---|---|
1 | >=50% | 100% | 1000 | 0% |
2 | >=50% | 100% | 1500 | 50% |
3 | >=50% | 100% | 2250 | 50% |
4 | >=50% | 100% | 3375 | 50% |
5 | >=50% | 100% | 5062 | 50% |
The example algorithm’s output when PoW plasma is 10% of the momentum’s plasma and the momentum is equal to or over half full:
Momentum Height | Momentum Fullness | PoW plasma | Difficulty-per-plasma | Difficulty-per-plasma change |
---|---|---|---|---|
1 | >=50% | 10% | 1000 | 0% |
2 | >=50% | 10% | 937 | -6.3% |
3 | >=50% | 10% | 878 | -6.3% |
4 | >=50% | 10% | 823 | -6.3% |
5 | >=50% | 10% | 771 | -6.3% |
With this algorithm, even a user with a significant amount of computing power, would not be able to occupy over 20% of momentum space indefinitely.
Fused Plasma anti-spam
Currently, whenever fused plasma is used to send a transaction, that plasma gets recharged once the transaction is confirmed. This means that, if transactions are prioritized based on plasma, a malicious user with a significant amount of QSR could easily outbid others for inclusion in a momentum.
This problem is relevant since we will probably have to continue to have a conservative network max throughput, even with dynamic plasma, at least initially. My view is that we don’t really have any data to justify raising this throughput limit. Raising the throughput limit is generally a centralizing force, so we would need to do benchmarking to find a throughput limit that can be handled by regular consumer hardware. We want users to be able to run their own nodes.
To work around this problem, we could introduce a dynamic plasma recharge rate, so that fused plasma gets recharged at a rate that is dynamically adjusted. Instead of only requiring one confirmation to recharge all fused plasma, the plasma would be recharged at a per confirmation recharge rate.
This will act as a counter force to the temptation of excessively committing plasma to a transaction. The more plasma committed, the longer it will take to get it recharged, limiting an account’s ability to occupy momentum space and freeing up bandwidth for other users. This recharge rate would be dependent on the current network utilization rate.
Example of the recharge rate algorithm (recharge rate = QSR/confirmation):
Momentum Height | Momentum Fullness | Momentum Recharge Rate | Target Recharge Rate | Recharge Rate Change |
---|---|---|---|---|
1 | 0% | 100 | 100 | 0% |
2 | 100% | 50 | 0.01 | -50% |
3 | 100% | 25 | 0.01 | -50% |
4 | 100% | 12.5 | 0.01 | -50% |
5 | 100% | 6.25 | 0.01 | -50% |
6 | 100% | 3.12 | 0.01 | -50% |
7 | 100% | 1.56 | 0.01 | -50% |
8 | 100% | 0.78 | 0.01 | -50% |
9 | 100% | 0.39 | 0.01 | -50% |
10 | 100% | 0.2 | 0.01 | -50% |
11 | 100% | 0.1 | 0.01 | -50% |
12 | 100% | 0.05 | 0.01 | -50% |
13 | 100% | 0.02 | 0.01 | -50% |
14 | 100% | 0.01 | 0.01 | -50% |
Another example:
Momentum Height | Momentum Fullness | Momentum Recharge Rate | Target Recharge Rate | Recharge Rate Change |
---|---|---|---|---|
1 | 100% | 0.01 | 0.1 | 0% |
2 | 50% | 0.02 | 1 | 100% |
3 | 50% | 0.04 | 1 | 100% |
4 | 50% | 0.08 | 1 | 100% |
5 | 50% | 0.16 | 1 | 100% |
6 | 50% | 0.32 | 1 | 100% |
7 | 50% | 0.64 | 1 | 100% |
8 | 50% | 1 | 1 | 56% |
From these examples we can see that every momentum has its own plasma recharge rate depending on how full the momentum is and what the previous momentum’s recharge rate was. The account chains that have an account block included in a given momentum will be subject to the plasma recharge rate of that momentum.
This introduces a “real” penalty for using fused plasma, since when there is high demand for momentum space, it will take a long time for plasma to recharge.
For example: If account chain A included an account block in momentum 5, and committed 10 QSR as fused plasma to that account block, it would take 63 confirmations (~10 minutes) to fully recharge the fused plasma.
Here is a pseudo-code example of how the committed, or “confined” plasma, is calculated so that the current available fused plasma for an account chain can be calculated.
Note: In order to not overload terms used in the existing go-zenon codebase, I’m using the term “confined” to mean the plasma that is committed to account blocks and that cannot be used until it has been recharged.
Fused plasma recharge rate considerations
One downside of this recharge rate idea is that it limits addresses to a low maximum sustained TPS. If the recharge rate is 1 QSR/confirmation, when blocks are at target fullness, then this means that every address is limited to a sustained throughput of ~0.01 TPS (assuming no PoW is used). This is also assuming the plasma base price is only 1.
For the vast majority of users this would probably not be an issue, but businesses and more complex use cases may well need a higher sustained TPS.
To alleviate this problem, we could also introduce a recharge rate multiplier that would linearly increase the recharge rate of accounts that have more than some threshold amount of QSR fused. This would probably have to be accompanied by some kind of account level limit of how many transactions could be sent within n momentums.
If the network max throughput can be increased, then the recharge rates could also be increased.
Attack scenarios
Below are a few examples of how the proposed ideas for dynamic plasma would help mitigate the effects of spam attacks.
Scenario 1: Fused Plasma spam
I simulated the following attack scenario with the example code, where the attacker owns 1M QSR and fuses it as plasma evenly to 20,000 addresses (50 QSR per address). His goal is to block users that have less than 50 QSR fused from using the network.
Attack result
------
Able to block users with less than 50 fused QSR for 29.17 minutes
Attack can be repeated in 227.27 minutes
From the result we can see that users with less than 50 QSR would basically have to wait a maximum of ~30 minutes for their transaction to be included in a momentum. They would also be subject to a very slow plasma recharge rate, unless they wait for network demand to decrease. The attacker could repeat the attack in ~3 hours and 47 minutes.
This is of course a highly simplified simulation since there would most likely be users with more than 50 QSR who would still be able to use the network during the attack, which would result in a longer waiting time for someone with only 50 QSR. On the other hand, if the attacker is only using fused QSR, then the PoW difficulty will decrease, making it easier for users to generate plasma via PoW.
Scenario 2: Fused Plasma spam
We can modify the first scenario a bit and say the attacker’s goal is to block users that have less than 1000 QSR fused from using the network.
Attack result
------
Able to block users with less than 1000 fused QSR for 0.67 minutes
Attack can be repeated in 430.50 minutes
We can see that in this scenario the attacker would only be able to block users with less than 1000 QSR for ~40 seconds and would have to wait ~7 hours and 10 minutes to repeat the attack.
Scenario 3: Pre-computed PoW attack
This needs more consideration, but I’m not sure if the dynamic difficulty adjustment is enough to mitigate this attack vector; someone pre-computing a massive amount of PoW over days, months, years, and then using it spam the network. Should PoW expire?
What about burning ZNN to generate plasma
The adjustment mechanisms presented in this post can be adjusted, so that new ways of generating plasma can be introduced. If it makes sense from a tokenomic, marketing, and technical standpoint.
Hard coded targets for different “plasma resources” can be introduced, or the plasma resources can directly compete with each other and let market forces dictate at what rate different resources are used.
For example, we could add novel ways of generating plasma, like burning some amount of Bitcoin would generate some amount of plasma. This may not actually make sense, but the point is we could potentially unlock new use cases like this.
Remarks
This post became longer than I initially intended. It has lots of stuff to consider, so I appreciate anyone taking the time to read through it. Since there are many angles to consider when it comes to a dynamic plasma solution, I may have failed to consider something important, so feedback and critique is welcomed.