Repository navigation
Proposal for dynamic network difficulty adjustment #2309
Description
There is a need to raise the difficulty in order to better protect against SPAM. Unfortunately this is at least partially not backwards compatible, because there is no mechanism for updating the network difficulty, the recipient metadata, or chan difficulty.
The main constraint is that I want this to not require a central instance, but at the same time not reduce anonymity.
The core of the proposal is a new network object, a difficulty vote. It will not contain any recipient, sender, encryption or signatures, only some random padding. It could have a fixed size. In metadata, it would contain
- either a creation time or a duration, to allow calculating the original difficulty
- current difficulty
- proposed difficulty
The client will verify the PoW as it does now, and then use a sliding window to calculate the current difficulty. There needs to be some wiggle room to avoid under/overshoots as the inventory contents are transient.
What this will allow is to have people who want to become "miners" and "bump" the network difficulty, making it more costly for the spammers. It would auto-adjust based on how much proof of work the miners contribute.
Deployment would happen in phases:
- Each of your addresses should track last announced difficulty. We already track last time the pubkey was sent. This is needed so that we know whether it's needed to announce an update or not.
- Allow pubkey objects to update metadata (difficulty). I.e. if you receive an updated pubkey from someone, you update the demanded difficulty. This currently doesn't work, after you receive a pubkey, the difficulty is never updated.
- Have pubkey objects to be auto generated when difficulty changes even if there is no request for them and the old ones haven't expired, but leave a bit of wiggle room (delay, range), to counter deanonymisation and DoS attempts.
- Add an option in keys.dat to enable generating difficulty vote and configure the target difficulty. Default off. Simultaneously, accept difficulty vote objects and calculate difficulty, just to see how it works. The resulting difficulty can be shown inside the network stats tab, and/or exposed via API.
- Allow tracking of objects that don't have sufficient difficulty for network-wide difficulty. Currently, they would keep getting redownloaded. We also need to be able to track them without having to store them fully in the inventory, so that we also reduce our storage of spam. For example, we'd track the inventory vector and expiration. We can use a new table in messages.dat for that.
- There should be new options in keys.dat to
- Use the difficulty vote to calculate which difficulty to announce for your own addresses (i.e. your own spam filter). Default off.
- Use the difficulty vote to calculate which objects to accept in inventory (i.e. a network-wide spam filter). Default off.
- Deprecate user-configurable difficulty and have the global one calculated from the difficulty votes to be used instead. This will make your own spam filter mandatory.
- Force migrate chans, because chans don't have a difficulty metadata and they are most affected by spam
- Force using difficulty for inventory filter (i.e. network-wide spam filter)
The difficulty check for accepting inventory objects should be more relaxed than for the local spam filter, to make network-wide transitions smoother.
Activity
smallzhong commentedon Mar 28, 2026
Peter, thanks for putting this proposal together. The spam problem is undeniably the most pressing issue Bitmessage faces right now, and I understand the intent behind it. However, I have some fundamental concerns about this approach, and I'd also like to take this opportunity to discuss the bigger picture.
On the Difficulty Vote Mechanism
Who Will Mine?
The core assumption of this proposal is that people will voluntarily spend computing power to generate vote objects. But unlike Bitcoin miners who earn coins for their work, Bitmessage "miners" would burn electricity purely to help the network filter spam — with zero economic return. If not enough people participate, the system is dead on arrival. If only a few participate, they effectively gain the power to manipulate network-wide difficulty — which is more dangerous than a fixed difficulty.
Difficulty Can Be Maliciously Manipulated
An attacker who rents cloud GPUs can flood the network with vote objects in a short period, pushing difficulty so high that ordinary users can no longer send messages. This would effectively be a DoS attack using the very mechanism we designed to protect the network.
No Chain, No Consensus
Different nodes inherently have inconsistent inventory contents — objects have a TTL (up to 28 days + 3 hours), and network propagation introduces delays. Computing a sliding window over inconsistent inputs will produce different difficulty values on different nodes. The proposal mentions the need for "wiggle room," but without a chain or any consensus mechanism, there's no fundamental solution to this problem. The end result could be messages accepted by some parts of the network and rejected by others — a de facto network split.
The Bigger Picture
Before continuing to layer complex mechanisms on top of the current protocol and codebase, I think we need to face some more fundamental issues:
The Address Model Copies Bitcoin Without Bitcoin's Prerequisites
Bitcoin makes addresses a hash of the public key because it has a chain — public keys are naturally revealed on-chain when spending UTXOs, and anyone can retrieve them. Bitmessage has no chain, so it needs a getpubkey mechanism to request public keys. This creates two serious problems:
First, getpubkey breaks anonymity. A getpubkey request contains the target address's RIPE hash or tag in plaintext. Any network observer can see that "someone wants to send a message to this address." For a protocol whose core selling point is anonymity, this is a fundamental design flaw.
Second, public key exposure enables targeted spam. In the current model, anyone can obtain any address's public key — either from pubkey objects broadcast on the network, or by actively sending getpubkey requests. Once an attacker has a public key, they can craft messages that the target is guaranteed to receive and decrypt. This means an attacker can systematically collect public keys and send spam to every reachable address on the network, with certainty that each message will land in the recipient's inbox.
A cleaner design would have addresses contain the public key directly, so senders can construct encrypted messages without "requesting" anything from the network. To network observers, all objects should look indistinguishable from random data — only the actual recipient should be able to identify and decrypt messages intended for them. This would eliminate both the anonymity leak from getpubkey and result in a fundamentally cleaner protocol design.
Object Type Is Visible in Plaintext Headers
The objectType of every network object (getpubkey/pubkey/msg/broadcast) is unencrypted. Combined with the size differences between object types, a passive observer can easily classify all traffic.
SHA-1 Is Still in the Signature Path
pyelliptic'ssign()defaults to SHA-1 as its digest algorithm, andhighlevelcrypto'sverify()tries SHA-1 first when no algorithm is specified. SHA-1 collision attacks have been practically demonstrated since 2017 (SHAttered).Python 2.7
It's 2026. Python 2.7 has been end-of-life for over 6 years. A security-focused communication tool running on a runtime with no security updates is a risk in itself.
My Take
Some of these issues are at the protocol level (address model, public key exposure, plaintext headers) and cannot be fixed without changing the protocol. Others are at the engineering level (SHA-1, Python 2) but fixing them requires breaking compatibility. Continuing to add new features on top of this foundation — new object types, inventory restructuring, forced chan migration, multi-phase deployment — carries enormous engineering cost with questionable returns.
Bitmessage's core vision — decentralized, anonymous, censorship-resistant communication — is still valuable, arguably more valuable than it was in 2012. But I believe the more pragmatic path forward is to start a new project with a from-scratch protocol design, using modern cryptographic primitives and modern engineering practices, rather than continuing to patch what we have.
PeterSurda commentedon Mar 28, 2026
Thank you for your feedback. These are reasonable arguments, but debateable.