Running a node and seeing peers disappear? Before you go hunting for a firewall problem: most of what looks like a ban isn't one. This post lists exactly what earns a ban score in the AntiQua network, what only gets dropped, and how to tell the two apart.
TL;DR
Every peer has a misbehaviour score. At 100 it gets banned. Below 100 is not a ban β the peer stays connected.
24 hours for full nodes, 1 hour for light and inbound peers.
Rate limits don't ban. Too many messages? The message is dropped and that's the end of it.
Two things ban you on the spot: failing the header checkpoint gate (+150) and parking more than 500 unconfirmed headers on a peer (+100).
Behaving well earns credit back, but it never lifts a ban that has already started.
The threshold
Ban score >= 100 -> banned
Ban score < 100 -> nothing happens
That second line matters more than it looks. A score of 95 is not "almost banned" in any operational sense β your peer is connected, syncing and relaying exactly as before. Scores accumulate, they don't degrade your connection on the way up.
Duration
Full node
24 hours
Light / SPV / inbound
1 hour
Light peers get the short ban on purpose: they sit behind mobile networks where the IP changes anyway, so a long ban would mostly punish whoever inherits the address next.
Bans are written to disk, so they survive a restart.
There is no manual ban. The node has no admin path that bans an address on the spot β reaching 100 through the scores below is the only way anyone gets banned. No operator, no plugin, no config file.
The two that ban you outright
Score
Reason
+150
During initial sync, the header checkpoint gate failed β the PoS anchor is missing or doesn't match
+100
More than 500 unconfirmed headers pending from one peer
Both are above the threshold on their own, deliberately.
The first: a peer that can't produce a valid checkpoint anchor is either running something that isn't this chain, or feeding you a fabricated history. There is no charitable reading of that.
The second is about memory. Headers you can't confirm sit in a cache. A peer that keeps stuffing that cache without ever delivering anything that checks out is filling your RAM, whether by malice or by being thoroughly broken. Either way you want it gone.
Two layers, two outcomes
Penalties come from two different places, and they don't behave the same way:
Layer
What it sees
What it does
Socket
The raw frame: length, encryption, message identifier
Scores and disconnects immediately
Dispatch
The parsed message: contents, sizes, counts
Scores and drops the message
So a malformed frame ends the connection then and there, while an oversized inventory list only costs the message. Both add to the same score.
Protocol and handshake violations
Score
Reason
Disconnects?
+50
Frame length of zero, or larger than the 4 MiB limit
yes, at the socket
+40
Message wrapper failed verification
yes, at the socket
+40
Header chain link broken
no
+35
Announce commitment claims an absurd transaction count
no
+30
Encryption failed to decrypt
yes, at the socket
+30
Message identifier doesn't match what the frame claims
yes, at the socket
+30
Handshake response failed verification
no
+30
Headers arrive out of order
no
+30
Far too many blocks in one message
no
+25
Payload empty after a successful verify
socket layer: yes
+25
Oversized headers, GetData or peer list
no
+20
Oversized inventory batch, invalid block inside a blocks message, transaction queue overflow
no
+15
A second hello after the handshake already finished, inventory flooding
no
+10
Replayed handshake response, invalid transaction payload, duplicate difficulty update
no
+5
Handshake seen-set capacity, empty rekey payload
no
None of these happen by accident on a healthy peer. They're the shapes a malformed or hostile client produces.
Sync, proofs and key rotation
Score
Reason
+30 per block
Pure GetData substitution β see below
+60
Headers you requested went largely unconfirmed within a 10-minute window
+25
Light client proof: merkle root doesn't match your header, or the proof is invalid
+20
Key rotation request out of sequence
+15
Light client proof: amount or recipient doesn't match
+15
Key rotation replay (sequence number too low)
+10
Announced a block height more than 500,000 above your tip
+10
Ping flooding, empty rekey ciphertext
+10
Pong nonce mismatch β not for inbound or SPV peers
+5
Key rotation rate limit, rekey response with nothing pending, malformed relay announcement
The +60 only triggers under real conditions: at least 8 headers sent, and fewer than 20 % of them confirmed inside the window. A handful of misses costs nothing.
The +10 for an implausible height catches a specific lie β a peer claiming the chain is half a million blocks further along than it is, hoping you'll chase it.
Encrypted messaging and multisig
The topic messaging layer β the one carrying encrypted messages and multisig confirmations β has its own penalties. They follow one pattern: rate limits are cheap, forged signatures are not.
Score
Reason
+5
Rate limit on subscribe, publish, fetch or forward
+10
Topic name oversized
+15
Payload oversized, missing message id, missing publisher key
+20
Missing or malformed public key
+25
Bad key length, binding mismatch, invalid signature length
+30
Bad signature on a publish, a forward or a multisig confirmation
A bad signature is the expensive one because there's no innocent explanation. An oversized topic name is a broken client; a message signed with a key that doesn't verify is someone trying something.
Substitution vs. honest extras
This is the distinction worth understanding, because it separates an attack from an ordinary sync hiccup.
When your node sends a GetData request, it remembers which block hashes it asked for. Any block that comes back with a different hash counts as a mismatch. What happens next depends on the whole response, not on the mismatch alone:
Attack β score +30 per block:
the response contained mismatches, and not a single block you asked for, and no compact stubs either. Somebody answered a specific request with entirely different blocks. That's a substitution attempt.
Ordinary β no score at all:
the response contained at least one block you actually requested, plus extras. The extras are simply discarded. This happens constantly and legitimately: tip gossip, a retried announcement, a compact block's parent.
Also no score:
a compact stub instead of a full body; an empty headers response; a request that came back holding only headers you already had; headers that fall outside the checkpoint horizon. All of these are re-requested or quietly closed.
That last group is deliberate, and the reasoning in the code is worth repeating: a node catching up from genesis will legitimately produce batches full of headers you already know. Counting those toward the unconfirmed cache limit would ban honest peers for the crime of being helpful. So they don't count.
In one line: the right block plus noise is a normal peer. Only noise, when you asked for something specific, is an attack.
What is NOT banned
Worth stating explicitly, because these are exactly the situations operators come asking about:
Situation
What happens
Too many messages per second
Message dropped. No ban. 60/s normally, 400/s while syncing
Handshake queue full
Dropped and logged, no penalty
An unknown message type from an older peer
Warning in the log, no penalty
Compact stub instead of a full body
Re-requested, no penalty
Extra hashes alongside a correct block
Extras discarded, no penalty
A GetData job with no hash list at all
Blocks discarded, no penalty
Empty headers response, or one with only headers you had
Re-asked, no penalty
Headers outside the checkpoint horizon
Node waits for a block to connect, no penalty
A second hello in the same session
Ignored
Late pong from a mobile or SPV peer
No penalty β late pongs are normal on mobile
Reconnect from a phone that changed network
No penalty, that's the expected pattern
An error while serving GetData
Connection closed, no penalty
Key rotation when the key material is missing locally
Connection closed, no penalty
Checkpoint, challenge, attestation, receipt and mempool-status messages
Logged or dropped, never scored
Any score below 100
Nothing at all
If your node is losing peers and none of the scored events above appear in your log, you're looking at the wrong cause. Check your own connectivity, your port forwarding, and whether you're behind a NAT that drops idle connections.
Arriving with the next node release
One group of penalties is written but not yet in the build the network is running: malformed compact block traffic (a compact block with no header, a prefill entry carrying no transaction, transaction-index lists that are empty or out of range) and light client requests whose block query is neither a height nor a hash.
Today those messages are dropped without a score. After the next release build they cost between +10 and +35. Nothing an ordinary node or wallet sends is affected β these are shapes that only a broken or hostile client produces. Watch the Core Changelog for the release.
What stays unscored either way: a compact block that needs a follow-up request, a reconstruction that falls back to a normal GetData, a block that simply isn't held locally, and a peer that never answers the capability handshake (it's treated as a full node and life goes on).
Earning credit back
Credit
For
β5
A valid pong
β25
Confirmed headers during initial sync
Credit never lifts an active ban. Once a ban is running, good behaviour reduces nothing β the clock has to expire. The credits exist so that a peer which occasionally trips a small penalty doesn't slowly accumulate its way to 100 over days of honest operation.
Eclipse protection: slots per subnet
An eclipse attack means surrounding your node with peers that all belong to the attacker, so you only see the chain they want you to see. The cheapest way to do that is to bring many addresses from one network block. So the number of peers from a single IPv4 /16 is capped:
Full nodes
Light clients
Inbound per /16
3
16
Outbound per /16
2
2
Light clients get 16 for a practical reason: mobile carriers put huge numbers of customers behind shared address space, so a whole city can share one /16. Three slots would be full before breakfast, and gossip is skipped for light peers anyway, so they can't be used to feed you a false view of the chain the way a full peer could.
Slot budgets overall: 150 full peers by default, 32 light, 256 for archive nodes, a hard ceiling of 512 β and at most 75 unauthenticated inbound connections, a number that deliberately does not grow when you scale the others up.
Separately, your node watches its own peer diversity: fewer than 5 distinct subnets across at least 8 peers flags a possible eclipse. That's a warning, not a ban of anyone β it tells you to add peers from elsewhere.
The second score β and what it actually does
Everything above is the P2P layer: protocol violations, score 100, 24 hours, real disconnects.
The consensus module keeps a second, much tighter score for chain-level misbehaviour β a double-spend attempt costs 8, a replay 6, the threshold is 10, it decays by a point a minute and entries expire after 30 minutes.
What it does not do, today, is disconnect anyone. That score is written into the consensus module's own table and logged. Nothing in the networking code reads it back to drop a peer. So if you're looking for the reason a connection went away, this isn't it β check the P2P scores above.
It is useful for a different purpose: those log lines tell you a peer has been sending you double-spends, which is worth knowing even when the node keeps talking to it. If you see them repeatedly from the same address, that's a case for looking at the peer yourself.
If you think you've been banned unfairly
Look for the actual scored reason in the log. Every penalty above writes one.
If the reason is a rate limit, a dropped message or a closed connection without a score: that isn't a ban, keep looking.
If it's +150: your node and the peer disagree about history. Check you're on the right network, and that your build has the checkpoint flag compiled in β a build without it is not consensus-compatible with release nodes. (What the checkpoints do)
If it's +100: that peer buried you in headers it never backed up. Usually a broken or badly out-of-date node rather than an attacker.
Consensus log lines about double-spends are not the reason your peer disappeared.
Questions about a specific log line? Post it below β with the surrounding lines, the reason string is what matters.
β Blythex