Proposal: Prevent dust attacks with minimum balances on addresses (pre-coordicide)

Introduction

IOTA fullnodes can be attacked with a so called “dust attack”.

An attacker could send small amounts like 1 iota to millions of different addresses because of the feeless nature of IOTA. This would lead to increased database size and snapshot file size. Fullnodes would run out of storage pretty fast.

An example

We need at least 49 bytes to store the address in the database and 8 bytes for the amount.
If an attacker would distribute 1 Miota on different addresses, he would increase the database and snapshot size by 57 * 1.000.000 bytes = 57 MB.
With 1 Giota, storage size is increased by 57 GB.

Proposal

Introduce a minimum amount of iota, which must be sent to on an address or at least remain there.
If a new value transaction is processed by the fullnode, which would lead to a ledger state where a single address has less than the minimum amount of iota, this value transaction is ignored by the fullnode/coordinator.

With this approach, dust attacks becomes much more expensive for the attacker.
It would not prevent the possibility to use IOTA for micro transactions, if the receiver address has at least the minimum amount of iota already.

Example code to calculate the minimum amount

Python:

attack_costs_dollar    = 1000000.0
price_per_miota_dollar = 0.25
maximum_db_size_MB     = 1000.0
size_per_address_bytes = 57

# The amount of allowed addresses to fill up the DB
address_count = (maximum_db_size_MB*1000000) / size_per_address_bytes
print("AddressCount: %0.2f" % (address_count))

# The amount of iota you could buy for the given "attack_costs_dollar"
amount_iota = (attack_costs_dollar / price_per_miota_dollar) * 1000000.0
print("AmountIota: %0.2f" % (amount_iota))

minimum_amount = amount_iota / address_count
print("MinimumAmount: %d" % (minimum_amount))

Output:

AddressCount: 17543859.65
AmountIota: 4000000000000.00
MinimumAmount: 228000

With 228Ki, it would cost the attacker 1 Million $ to increase database size by 1GB at a market price of 0.25$.

Steps to implement this

  • Agree on a reasonable minimum amount (e.g. 1Miota or 500Ki)
  • Implement “white flag conflicting transactions”
  • Add the minimum amount as another rule for calculating the balances in “white flag” approach
  • Implement a check in Trinity, which prevents users to create transactions that would lead to an invalid ledger state
1 Like

Enforcing minimum amount breaks micro-transactions. Preventing transaction creation in Trinity opens door for DoS attacks. Applying EC (https://medium.com/@comefrombeyond/economic-clustering-and-iota-d3a77388900) for minimum amount solves the problem, and still allows micro-transaction processing on mainnet.

Hi Chris!

As I said in the first post, micro-transactions would still be possible if the receiving address already has the minimum amount. You can still send your 1 iota’s if the receiving address is pre-charged with 500ki for example. I can’t imagine an use case today or in the future, where this wouldn’t be suitable. If you want to charge your electrical car, the first transaction of this “micro-payment” is a bit bigger, and that’s it. You won’t charge your car with a fraction of a kWh.

How does “Preventing transaction creation in Trinity” opens a door for DoS attacks?
Could you explain that a bit? :sweat_smile:

Applying EC to the mainnet now is a whole other story than just adding this small additional rule to the “white-flag” approach.

Hey, I just see that part of EC which erases balance that is not being spent often is an easier change to make.
Regarding wallet, suppose an address has 10001i and user wants to spend 10000. It’s a bit confusing to prevent such transactions I think.

I’m fine with this going together with the white-flag (which is a strictly temporary measure), but (as I wrote on Discord), I think that an ideal solution for the dust attack would be: everybody is free to issue any transactions, even of 1 iota and keep them on whatever addresses. However, when you do this, you put you own funds at risk: in case the DB grows too much, the nodes would start forgetting about such addresses, and then it becomes increasingly difficult to spend such funds. I recall CfB envisioned this kind of solution (as part of the EC idea).

This would be quite in the spirit of IOTA - it is about freedom. Just to formulate it a bit differently: instead of binary rules of the sort “if you do X, you’re fine, if you do not-X, you’re screwed”, we want to introduce also a “grey” area: “if you come close to the boundary of X, you risk your funds”. Obviously, such rules must be defined in a way that it’s unlikely that we’d get a global fork that way.

This is not so easy to achieve, of course. But, well, we have some tools in our toolbox (voting, mana, …). And we are not afraid of challenges (last time I checked :wink: )?..

1 Like

So we need to do a change to the wallet as well that will notify the users that they should probably transfer their loose change.

Even though this can be implemented while we’re doing white-flag and may be released with it, it shouldn’t be a blocker. Besides changing the node code there is farther overhead. I think this deserves its own RFC and shouldn’t be part of white-flag RFC.

Another idea: Remove dust addresses & reduce the supply after X milestones.
Dust addresses should just be stored as a pair of their trytes & latest milestone index that affected their balance. Thoughts?

Isn’t the rate control approacches already taking car of this? Someone with only 1 Giota has a low amount of mana. As their try to dust their iotas they would have the increasing PoW cost and lower priority, so an attack like this would take years since it needs 1bi transactions to be done.

Alternatively one could introduce a 1s processing time between transactions being gossiped from he same address, what wold make the process take at least 37 years unless he parallelizes the process, but would still be quite a long time to achieve something.

I think we need to create a separate thread for coordicide.

Anyhows for pre-coordicide I am against loosing balances and changing the supply of iotas.

@muXxer is right. This is an important topic for pre-coordicide. We also have to make sure that this attack vector is not available in coordicide as well. While I agree with him, I see a potential issue with losing a lot of good IoT use-cases here. If you are interested in the details, I can write down some scenarios, where this could be a problem.
So, I also see an issue with the micro transactions. Like @chrisd does.
Maybe it makes sense to close the vector for pre-coordicide and find a way to enable micro transactions in coordicide and closing this attack vector. Even, if this currently result in restricting the use-cases.

As mentioned by Darcy, this problem will be solved by the combination of adaptive PoW and an appropriate scheduling policy based on mana in Coordicide.
As for pre-Coordicide, I admit we haven’t done much research on the topic, which is not trivial to solve. Adding a minimum threshold is an effective solution, even though it may prevent micro-transactions. I believe that implementing such a “patch” or not will depend on whether dust attacks are a current existing threat, or it is more important to safeguard the IoT use case.

This is not an easy problem to solve, because once we have colored coins very small amounts will probably be the norm. For example the Smart Contract system design needs a single colored coin to be used as chain constraint.

Ok let’s dig into numbers: 57 PB per Pi x 2,7 Pi are about 154 PB. If you need a distribution of factor 16 you are at about 2,5 EB. Good. In other words you would need a torrent-like DHT network of 2,5k x 1 PB (~80.000 € for cheapest SSD or ~28.000€ for rent per month) or 2,5 mio x 1 TB nodes holding snapshot data only. That’s doable in my opinion. At the beginning there will be only unicorn-sized companies able to build this up. But as the network grows the cost for every node will shrink and the network will be fully distributed in the next 5-10 years.

This limits the data transfers for requests and propagations to there bare minimum.

2,5 EB is the worst-case scenario. 0.1-0.5 EB is more likely. And for starters it might be enough to have a lower factor of 4 to 8. Then you would be at 25 PB - 125 PB or 50 PB - 250 PB with a total cost of 20 mio € max for ssd space for one big entitiy or 20k € for any company or 20 bucks for a normal node at home. That is doable.

These nodes holding a very valuable part of the network. There should be incentive model. 1 TB “slow” SATA SSD vServer aren’t cheap now (contabo 27 € for 1,6TB). A RaspiBlitz is not very cheap too. But if the IF would work with them then they might build a special very streamlined and low-cost 2 TB IOTA node that can be sold worldwide for let’s say 100 €. At 2,5 million sold items the network would have its save and censor-free baselayer. Even routers like AVM Fritzbox could hold a 2 TB SSD inside.

That are my thoughts. I mean DHT apps like Torrent and Emule are good old school stuff. They proofed that they work efficiently.

we already work on such a solution with RaspiHive

anyhow, in my opinion minimum balances influence the usabillity in such a drastic way, that i´m absolutelly not happy with this solution.

Could there be comething like a minimum locked funds per each working address? Say 10ki that can be redeemed only after you close the address? This value could also go down over time as better HW or sharding comes along.

Maybe and most sure i’m not understanding this pretty well but…

However, when you do this, you put you own funds at risk: in case the DB grows too much, the nodes would start forgetting about such addresses, and then it becomes increasingly difficult to spend such funds. I recall CfB envisioned this kind of solution (as part of the EC idea).

Does this mean that we may lose funds on our wallets? What criteria is followed by nodes to choose which addresses’ balance they remember?

You could just split at every transfer your funds to two new addresses. So after n steps you have approx 2^n~10^(n/3) i. For 1Gi this requires only about 30 steps. Its like the wheat and chessboard problem. If its computationable possible at all to dust attack 1Gi this rule does not seem to prevent it.

Not sure about this. Is the plan to allow for txs to be sent with only PoW in non-congested times? Then lets say the network is not fully congested most of the time and there is the possibility to send txs at 100tps (on average) with just PoW. Then with the rice and chessboard approach you can dust attack 1Gi in about 110days. If 1000tps can be sent with only PoW then it takes only 11 days.

IOTA is a permissionless protocol, this proposal will be week iota’s permissionless.
And dust attacking will still be possible by modified node software.