[SPAN mitigation] Increased minimum pow difficulty as function of transaction amount

This days seens someone is trying to bloat the ledger with some span transactions or at least is using the network in a way that is not sustainable.

I would like some help to think about a simple change that could help to increase the cost of span, or at least slowdown the span rate. This is not intended to be an entire solution for the problem, but one of many inprovements to create a most robust network.

Why not implement a different minimum pow multiplier based on the amount of transaction. This way transaction with more "value" would be incentivised while micro/dust transactions would have less incentive or at least you should think about if it is worth while to do multiple dust transactions instead of a bigger one grouping your multiple small transactions.

For example ... every transaction greater than 0.1 Nano would have a pow minimum multiplier of 1X, then for smaller transactions every decimal place would add +1 to the dificullty multiplier.

For example:

0.01 Nano transaction = 2X minimum multiplier
0.001 Nano transaction = 3X minimum multiplier
0.0001 Nano transaction = 4X minimum multiplier
0.0000000001 Nano transaction = 10X minimum multiplier

I know this kills a little bit the Micro Payments/IOT use cases, but i'm aligned with the position Nano network is intended to be only used as currency and not a data transfer protocol or anything else, so this sounds like a reasonable trade-off.

I think this measure + precomputation pow limit period + prunning would improve a lot the network.

I hope you can contribute with the idea pointing if there is some issue i can't see in this scenario or tell me why this could not be a good ideia.

Thanks in advance


Since there's no "fee" (other than the PoW itself), you (as a spammer) could continually send 0.1 Nano forever.

It may reduce the pending-blocks since there's more incentive to confirm such transactions in order to keep spamming. However, that "anti-spam" is useless for anything else.

Also, fiat value changes with time. Today the value of 0.01 Nano is negligible, but it might change in the future. In the end, most of the transaction could be < 0.01 Nano only because 0.01 Nano is valuable enough.

I agree the spammer could send 0.1 Nano continuously, but probably he would want to receive this transaction and get it back, otherwise the span cost would be increased since you are "burning" a quantity of Nano thats not neglectable. Beyond that, the cost to parallelize the attack increases as well cause right now we can create milions of parallel transactions costing almost nothing cause the pow cost to send 1 raw is the same as send 1 Nano. I agree with the fact fiat value changes, but it takes time to change significantly and it would need to multiply 10X in order to the pow start to change, i don't see this being a problem in the short term unless nano skyrockets to 100k USD (Or maybe more) in a short period of time.

The point here is just increase the cost and reduce the throughput of the attacker cause his computational power isn't unlimited. In this scenario the attacker would probably receive the transaction and probably send it back, and this would make the account prunnable.


I also like the idea of PoW multipliers by orders of magnitude (previously suggested here), but you'd probably want to account for the lowest GNI countries in the world + the possibility of a 10000x, to come up with a more evidence-based floor:

Significantly increase PoW for every order of magnitude less than "unano" (10^18)

  • Rationale: Lowest GNI in the world is ~1/1000 of the US
  • Humans don't transact in 1000ths of a cent; at 10 cents/Nano, .001 cents == .0001 nano; add another 3 orders of magnitude for lowest GNI country == .0000001 is lowest currently reasonable, add 4 more orders of magnitude for if Nano ever goes 10000x (10x current world GDP), aka .00000000001 becomes a good soft floor
  • Risks: "True" microtransactions/message encoding, floor too low to discourage a hacker, floor too high to allow for real world use in the places that could use Nano the most

I think that particular idea is less about prioritizing high amount transfers, and more about increasing the cost of wasting network resources with transactions that provide no real world value. It's about focusing on the human-to-human digital cash usecase over anything else

You could do something like increasing the required PoW by 33% for every order of magnitude below "nano" aka 10^24, and that would naturally discourage extremely low value transactions while not making them impossible. It would also act as a pseudo-auto scaling mechanism for hardware improvements vs PoW since that will loosely correspond with Nano market capitalization increases (hopefully)


I think the focus should remain with Nano being used as a currency ie. a transfer of value.

As soon as it's no longer value that you're transferring but rather a message / signalling event that shouldn't have priority for the the network.

While I wouldn't want to discourage microtransactions, those transactions should still represent a transfer of 'value'. A value of 0.00001 nano at current market cap is probably already well below the threshold that any single transaction anywhere on the planet will be made between two parties.

It should also be noted that nothing will be set in stone if this was put in place in a new release, this would obviously be subject to change if it proves detrimental but I do think that some protocol change is necessary sometime soon to combat spam risk even if the initial version may be a little heavy handed.

It is obviously too easy to spam inappropriately at the moment.

Edit: Just to add I think having PoW scale up with smaller transaction values (or remaining account balance to prevent new acount dust spam) is a great simple to implement and understand solution to spam.

1 Like

Spam sending 0.1 Nano is not such an issue since the attacker will not want to loose all value. That means it will sent to 'real' accounts from which the funds can be recovered. That in turn will mean that pruning will be able to remove many of those transactions.

The real problematic attack at the moment is dust spam to new accounts which cannot be pruned away.

1 Like

For me, that is the opposite. That may reduce the amount of "pending-blocks" that helps the pruning, but it also creates new accounts since you would like to receive such a transaction... Each new account is a new account, so the tx can't be pruned (a pruned node will need to hold each account's frontier-block).

There's many ways of store data. If the PoW is related to the transferred-amount: the best store data will be the "address-chain".

Two of them are:

  1. Single address to pending:

    The best way to store data (up to ~72 bytes per tx) is by using a single account. That will sends a < 0.1 Nano and use the "Destination"/"Link" (32-byte) and the "Representative" (32-byte).

    Side-Effect: Creates multiples pending-blocks (which takes ~80 bytes, even for pruned node).

    Disadvantage: Can be pruned and will pay higher PoW (since each tx is < 1 Nano).

    Advantage: Store up to 72byte per tx, almost for free. A single bulk_pull_blocks recovers all blocks and a single confirm_ack can confirm all blocks.

  2. Address to address:

    If such "Value-Based-PoW" is applied (as suggested by @Qwahzi and @VinickGold), that would be the best option: Each transaction can hold 32-byte, using the "Representative" field. It will make an "address-chain". So, you can send 1 Nano to "Account A" (including the data on "Representative"), then "Account A" sends 1 Nano to "Account B" (again, using the "Representative" as a data-field). Then, the circle repeats: Account B to Account C to Account D to Account E...

    Side-Effect: "account-chain" creates many accounts. That eats more space than a single pending-block. Following the definition of the "Pruned-Node" (on the Whitepaper), the pruned-nodes must hold the frontier-block of each new account (which have +176bytes, not just ~80bytes of the pending-block information).

    Side-Effect: By default, it will need to call Confirm_Ack more often since the node needs to follow a path of address. It might be mitigated if one account points to the end (the then walks backwards, from the last tx to the first, using the "Previous" field). But, the bulk_pull_blocks still need to be the request of each new account.

    Disadvantage: Store fewer data per tx (up to 32 bytes per tx or 32bytes for each 2tx).

    Advantage: Can't be pruned (by the definition of the Whitepaper). It will pay more PoW per data, but still better than pay 10x PoW, anyway.

If you are creating new accounts, it can't be pruned anymore. Pruned-nodes must have the frontier of each account, so you do the following:

Account A: Open (1 Nano) -> Send to Account B (1 Nano);
Account B: Open (1 Nano) -> Send to Account C (1 Nano);
Account C: Open (1 Nano) -> Send to Account D (1 Nano);
Account D: Open (1 Nano) -> Send to Account E (1 Nano);

The total balance of Account A, Account B, Account C and Account D is 0 Nano. But, each account holds 2 blocks and the lastest block (the frontier) you must keep, even if you are a pruned-node (following the original Whitepaper and the definition of the "Pruned-Nodes"). You can, of course, split and "fork" the transactions instead of just 1->1->1->1.

I don't see why you would need to keep accounts with 0 balance, if you would send to that account again it would be opened again

If you delete the account you have two problems:

  1. You (as a bootraping node) can't reach the Genesis-Block anymore.
  2. You (as a node, without the block) is vunerable to double-spending.

Basically, consider:

Account A: Open (2 Nano) -> Send to Account B (1 Nano);
Account B: Open (1 Nano) -> Send to Account C (1 Nano);
Account C: Open (1 Nano)

So, "Account B" have 0 balance, so it will be deleted. That is the information that you (as a node) would have:

Account A: Open (2 Nano) -> Send to Account B (1 Nano);
Account C: Open (1 Nano)

Now, the problems:

I (as one random node, trying to sync) would ask:

  • From where the "Account C" balances comes from (sending one msg_bulk_pull using the "Previous")?
    You can't reply, because you deletes it.

I'm trapped, I can't reach the Genesis, so "Account C" is invalid account at all.

I (as a spammer) can later publish:

Account B: Open (1 Nano) -> Send to Account X (1 Nano)

  • How did you know that my transaction is already claimed and sent to "Account C" before? You don't have the data to compare.

Then you have a forked account:

Account B (1): Open -> Send
Account B (2): Open -> Send

If I publish a new "Send", which "Previous" should I use? How the msg_bulk_pull_account and msg_bulk_pull will behave having two accounts under the same key? What happens if I republish the old chain (you don't have the data, right?).

1 Like

One can send 100 nano from one address to a new one an leave every time 1 raw on the old one.

That is why the check would be that both the send value as the remain value needs to be above the threshold. If either are dust then the PoW scaling kicks in.

You have a point. I haven't followed the pruning proposels but i would have assumed that more than just the frontier blocks would be kept so that account B would not be pruned until it no longer had any links to other frontier blocks.
But even then you would have forked accounts on full historical nodes though it should be obvious why those forks exist - the one ends with 0 balance and the other always starts from 0 with a receive value.

Yes, the atacker can still do transactions, this isn't the point. The point is with this change the cost to paralelize an attack would increase or the throughput of the attacker would decrease. Right now with just one Nano (or less) the the atacker can create a farm of machines doing parallel dust transactions and it will take years to spend that entire Nano doing the span, but the ledger size would skyrocket. With a increased pow scaled with transaction amount, the atacker would need to:

A) Calculate greater pow to perform dust transactions (This would end up being more computatinally cost)
B) Spend a greater amount of Nano to create transactions with easier pow (This would end up being costlly cause the atacker would need to buy Nano and burn the supply, or at least receive it back in someway that would facilitate prunnig)

Both options would end up increasing the cost of an attack.

The point here is just increase the cost for the span to a point where one person doing millions of transactions would be cost ineffective, but doing a small number of transactions or transactions with more value to the network would have an acceptable cost. Since we can't verify identity to "ban" the spammer, cause he just need to create a new account this resumes to the simple fact we need to ajust the cost of operation (In this case Pow) and be able to invalidade Pow calculated in advance considering a reasonable period of time. But an user with infinite capital/money would always be able to circunvent the span protections no matter what is implemented even for other cryptos. Fortunately, no one in the world has infinite capital to spend spamming.

Summarizing everything:

In my opnion, there is no way to stop span totally if you can't verify identity of someone, the only thing we could do is increase the cost of span (Hardware, Pow and Coins) for a level that is economically not viable.