PoW Multipliers (Anti-Spam Brainstorming)

Some brainstorming below to generate discussion:


  • Minimize hard-coded limits that require node/protocol updates over time
  • Incentivize receives to make pruning easier
  • Prioritize human-to-human transactions (occasional + real world value)
  • Discourage "bad" behavior (hard to prune, ledger bloating, network saturation)


Significantly increase PoW for open transactions

  • Rationale: Typically happens infrequently; reduces ledger bloating; people understand opening accounts before using them (+harder to burn transactions on accident?)
  • Risks: Exchanges/light wallets (but they could charge users for more accounts); Can still send to unopened accounts (see next idea)

Significantly increase PoW for sending to unopened accounts

  • Rationale: Reduces bloating; Incentive to open accounts (easier to prune)
  • Risks: Uneducated users vs exchanges/lightwallets? Less "privacy" due to incentivizing address reuse; people can still not receive transactions after the initial open

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

Increase send PoW based on number of unreceived transactions CREATED BY the sending address:

  • Example: nano_a has sent 100 unreceived transactions == 2xPoW for next 100
  • Rationale: Encourage receiving transactions for pruning; harder to spam
  • Risks: Light wallets & exchanges that open accounts and send transactions for other people, BUT exchanges could check withdrawal addresses for pending receives first (and notify users to pocket their funds before they'll allow withdrawal); Light wallets have different sending addresses; Could also do a rolling window to account for light wallets/exchanges/sending to people that never receive?
  • Requiring extra DB reads/calculations to determine PoW validity?

Increase send PoW based on number of pending receives TO destination address:

  • Rationale: Encourage receives for pruning
  • Risk: Spam DoSing legitimate users

Increase PoW costs for each order of magnitudes increase in sending volume vs a rolling window:

  • Example: 100 vs 1000 vs 10000 transactions in an hour (increase PoW cost for each)
  • Rationale: Really high orders of magnitudes almost always come from spammers
  • Risks: Lightwallets and exchanges

Per-node whitelisting of known-good services for lower PoW/prioritization under load:

  • Rationale: Differentiating between spam and high volume services; could potentially allow for increasing the base PoW without impacting good services as much (if enough PRs whitelist them)
  • Risks: Potentially anti-competitive for new Nano businesses;

Limit pre-computing PoW (time-based nonce?):

  • Rationale: Prevent mass accumulating and dumping blocks
  • Risks: The Nano network has no sense of time

Types of spam to consider

  • Opening new accounts - Storage risk
  • Valid transactions (high or low value) in a loop (Epstein spam) - Network saturation risk + storage risk w/out pruning
  • Sending and never receiving - Hard to prune (storage risk)
  • Sending to unopened accounts - Hard to prune (storage risk)

Other thoughts

  • All of the above increases would be multipliers vs whatever the baseline send PoW is
  • There is a constant balance battle between legitimate services and spammers
  • Full node operators are almost never affected since they do their own PoW
  • If all services could enable client-side PoW, it would be a lot easier to prevent spam without impacting legitimate services
  • If receives were auto-received (no signature required), pruning would be a lot easier
  • Some of the above ideas are not intuitive; users would have to understand the protocol to understand why some sends/receives are harder than others

These are excellent ideas. However, I think we should be realistic on what could possibly be implemented, the more simple the better. Apart from the already implemented dPoW and the future different PoW design, I suggest to differentiate PoW difficulty by block type.

PoW-difficulty from lowest to highest:

  1. Receive block: default network difficulty
  • Rationale: it's common sense, we want to make receives seamless. There is no danger that a spammer would saturate the network with receive blocks only as they would be discarded by the nodes.
  • Risk: none
  1. Change block: 2x default
    Rationale: representative changes do (or should) not happen frequently, there's plenty of time to pre-calculate the PoW, however, as others have suggested before, a theoretical "change block attack" could happen where the malicious node would saturate the network with extreme amount of change blocks.
    Risk: none

  2. Send block: 4x default

  • Rationale: If we design nano to be a digital currency of choice between humans, it is unreasonable to assume that a human may want to do multiple transactions per second. A higher difficulty PoW for send blocks would make the the spamming more expensive by default even when the network is not yet close to saturation. Average users would not notice difference as their PoW would be pre-calculated.
  • Risk: Slightly increased confirmation time. Light wallets backends and exchanges (hot wallets) would suffer. Exchanges could mitigate this by distributing the funds to multiple hot wallets.

4: Open block: 10x default

  • Rationale: Again, looking things from the human user's perspective, you don't need to open multiple accounts per second. We must discourage high frequency broadcasting of open blocks by the same node.
  • Risks: Services that create a new address for every transaction would suffer along with users...

Regarding send transactions, the ideal situation for me would be having everyone use client-side PoW (only a few second per phone), and then restricting high volume/bad behavior in other ways. That's not really possible at the moment though, since PoW costs between high and low end devices are so different.

Regarding open blocks, it's possible to send to unopened accounts, so you'd have to pair the increased account open cost with an increased cost for sending to unopened accounts

Wouldn't checking those conditions make the protocol a lot slower? How hard is it to check whether an account is opened?

1 Like

Since work is the first thing checked before using additional resources to further validate a block, then checking whether an account was opened to determine the level of valid PoW required would mean a disk check is needed, and thus open up potential DOS attack vectors, unless optimizations can be designed to avoid that (accounts list with open status in RAM, etc.).


So that would prevent us from having a PoW multiplier based on the volume of send transactions to an unopened account (since we don't know if it's unopened unless we read from disk), but we could still increase the required work for open blocks themselves (i.e. if "previous" value == 0, use 2PoW). Would that help reduce ledger bloat from new account spam at all? I guess if we're not careful this could actually incentivize spamming to unopened accounts. It almost has to be paired with increasing the cost to send to unopened accounts somehow

I'll have to think about the other stuff some more. The next thought I had is to keep an in-memory rolling window count of sends from an address that only decrements if a receive is seen from the destination address. If no receive is seen after X transactions in Y time, the PoW required from the sender could be multiplied. That might incentivize receives and decrease spam. Not sure yet though, still thinking about it. Issues might include: 1) receive transactions linking to the previous block hash and not a sending address, 2) receives not related to the sender decrementing the counter, and 3) balancing sender PoW difficulty vs number of receives

Wasn't there a discussion some time ago that there should be a relation between amount sent and PoW difficulty required? What happened to that idea?

Prioritizing high amount transfers doesn't help that much in preventing spam. You could send 100 nanos back and forth between two or more accounts. It does force the spammer to create a receive block though, so I guess it would make pruning more efficient.

Exactly, spammers would have to open accounts if they wanted to spamm that way and prunning would take care of the rest.

My view is that there isn't a single anti-spamm measure that will save Nano, there needs to be a bundle of them to be efficient.

1 Like

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)