Zebra 6.2.3 Release

Zebra 6.2.3: Peer Connectivity Hardening

This is an optional release with a set of peer connectivity improvements. It is targeted at operators who see issues with their node’s peer set.

Improvements

Outbound Slots No Longer Fill With Non-Serving Peers During Sync

Outbound peer slots could previously fill up with peers that advertise no services, which could stall a fresh sync at genesis when most reachable listeners are non-serving. While syncing, Zebra now requires the NODE_NETWORK service from outbound peers; at or near the network tip it continues to accept non-serving peers, such as pruned nodes, as before. (#11071)

Proactive Replacement of Dropped Outbound Connections

The peer crawler now queues a connection attempt on each crawl interval for every spare outbound slot that has a ready address book candidate, so a dropped outbound connection is replaced promptly. Previously, new connections were only attempted when the peer set ran out of ready peers, when a crawl turned up new addresses, or when the node had no outbound connections at all. Zebra now keeps dialing until the outbound connection limit is reached. (#11102)

Larger getaddr Responses

Zebra now shares up to half of its address book in response to a getaddr request, up from a quarter, so peers can discover more of the network from each response. (#11103)

More Tolerant Stall Detection Near the Tip

The stall detector no longer disconnects peers for empty FindBlocks or FindHeaders responses while the node is within 1,000 estimated blocks of the network tip, which previously could be mistaken for a stall during the normal gaps between blocks near the tip. (#11122)

No More False Bans Around the NU6.3 Branch ID Transition

Mempool transaction relay no longer penalizes peers for adjacent NU6.2 and NU6.3 branch ID mismatches within 40 heights of NU6.3 activation, avoiding unnecessary bans caused by the temporary chain-tip divergence that is expected around any network upgrade boundary. (#11113)

zcashd-compat Sidecar Pinned Ahead of NU6.3

The embedded zcashd-compat release manifest and installer script now pin sidecar zebra-compat-v1.1.0, which follows Mainnet past the NU6.3 (Ironwood) activation at block 3,428,143. The previous zebra-compat-v1.0.0 sidecar predates that activation height and stops following the chain at that block. Supervised deployments using zcashd_source = "embedded" must upgrade, or set zcashd_path to a current sidecar binary, before activation. (#11112)

Other Changes

Retained Peer-Supplied Block Hash in Sync Responses

Chain synchronization now keeps the final block hash a peer returns in a FindBlocks response instead of discarding it to work around obsolete zcashd behavior. (#11093)

Updated librustzcash Dependencies

The orchard, zcash_keys, zcash_primitives, zcash_proofs, and zcash_transparent crates have been upgraded to their released NU6.3 versions. This is a dependency update with no behavior change. (#11111)

Upgrading

We encourage operators who are experiencing peering issues, or who want to be proactive about avoiding them, to upgrade to 6.2.3. You can find the release on GitHub, crates.io, and Docker Hub.

If you run a supervised deployment with zcashd_source = "embedded", upgrade to this release, or point zcashd_path at a current sidecar binary, before the NU6.3 (Ironwood) activation at Mainnet block 3,428,143, since the previously pinned sidecar stops following the chain at that height.

Contributors

Thank you to everyone who contributed to this release:

@arya2, @jvff, @nuttycom, and @upbqdn.


Zebra is the Zcash Foundation’s independent, Rust-based implementation of the Zcash protocol. Learn more at github.com/ZcashFoundation/zebra.

8 Likes

Thank you very much.

v6.2.3: “attempted to add a banned peer addr” logged ~300k times in 24h

Running zebrad 6.2.3 on Ubuntu 24.04 (ThinkPad L450, 8 GB RAM), Mainnet, fully synced.

After a peer is banned for misbehavior, crawl_and_dial repeatedly attempts to re-add the same banned address to the address book, emitting a WARN each time — dozens of times within the same millisecond:

2026-08-03T19:20:06.585024Z  WARN crawl_and_dial{new_peer_interval=61s}: zebra_network::address_book: attempted to add a banned peer addr to address book change=UpdateAttempt { addr: <redacted>:60886 }
2026-08-03T19:20:06.585102Z  WARN crawl_and_dial{new_peer_interval=61s}: zebra_network::address_book: attempted to add a banned peer addr to address book change=UpdateAttempt { addr: <redacted>:60886 }
[... 17 more within the same millisecond, same address ...]

I archived my log yesterday, so this is roughly 24 hours of runtime: 297 881 occurrences of this single warning, in a 61 MB log file. It is the overwhelming majority of the file.

The ban itself looks legitimate:

WARN zebra_network::address_book: banned ip and removed banned peer addresses from address book
  updated=MetaAddr { addr: <redacted>:8233, misbehavior_score: 100,
  last_connection_state: Responded, user_agent: Some("/Zebra:6.2.3/"),
  negotiated_version: Some(Version(170160)) } total_peers=2090 recent_peers=1

Note total_peers=2090 but recent_peers=1, dropping to 0 a minute later.

What looks wrong is that the crawler keeps selecting an address it has just banned, rather than excluding it from the candidate set. Two questions:

  1. Should banned addresses be filtered out of the crawler’s candidate selection instead of being rejected at insertion time?
  2. If the repeated attempts are expected, could this be logged at DEBUG or rate-limited? At this rate a long-running node produces gigabytes of logs.

Context, likely unrelated to the above: my node holds only 1–5 peers. Of the negotiated peer versions I could extract from the log, 38 were 170140/170150 and only 7 reached 170160, so most candidates are rejected at handshake on protocol version. I take this to reflect the current state of NU6.3 migration across the network rather than a Zebra defect — mentioning it only in case a small candidate pool contributes to the crawler hammering the same few addresses.

Config is standard: peerset_initial_target_size = 75, default max_connections_per_ip, listen_addr = "0.0.0.0:8233", standard DNS seeders (I removed mainnet.is.yolo.money, which no longer resolves — the others return 25, 7, 1 and 2 addresses respectively).

Happy to provide a fuller log excerpt or run any diagnostic.


Pense à vérifier que les adresses IP sont bien anonymisées si tu colles des extraits supplémentaires — ton log les affiche déjà en v4redacted, donc c’est géré nativement par Zebra.

3 Likes

Thanks for letting us know about this. We have been working on the fix and it will be resolved in v6.3.0 which will be released soon.

1 Like

Follow-up: near-total network isolation on a fully-updated node — 97% handshake failure, zero genuine inbound

Following up on my earlier report about address_book log volume — thanks @nsheep for confirming the fix lands in v6.3.0.

While investigating, I ran into what looks like a broader connectivity problem, and I’m not sure whether it’s expected post-NU6.3 or worth flagging.

Setup: zebrad 6.0.0 on Ubuntu 24.04, mainnet, clearnet (no Tor), standard DNS seeders, listen_addr = "0.0.0.0:8233" with the port forwarded, peerset_initial_target_size = 75, default max_connections_per_ip. Outbound connectivity verified working (raw TCP to port 8233 succeeds). Node is at height 3439278.

Log window: 2026-08-04 18:22 to 2026-08-07 11:00 UTC (~2.5 days).

On startup (2026-08-06 23:42), from seeds plus a 75-entry disk cache:

add_initial_peers: finished connecting to initial seed and disk cache peers
handshake_success_total=2 handshake_error_total=57 outbound_connections=2

Two successful handshakes out of fifty-nine attempts.

Protocol version rejections over the full log window:

14  Version(170140)
16  Version(170150)

Thirty peers rejected for negotiating below 170160.

Steady state is a single active connection, and the syncer stops:

WARN sync::progress: chain updates have stalled, state height has not increased
for 47 minutes ... sync_percent=99.995% current_height=Height(3439278)
network_upgrade=Nu6_3 is_syncer_stopped=true

with failed to make outbound connection to peer error=Elapsed(()) repeating — 670 occurrences over the window.

Self-dialling: rejecting self-connection attempt appears 338 times, the node dialling its own address from the cache. Against 670 failed outbound attempts, that is a significant share of dial capacity spent on a candidate that can never succeed — and it compounds on an already-thin candidate set.

No genuine inbound connections. Over the same window, connected_addr=In( appears 169 times — every single one of them is a rejecting self-connection attempt. Filtering those out leaves zero real inbound connections in 2.5 days, on a node listening on 0.0.0.0:8233 with the port forwarded. Combined with the outbound picture, the node is effectively isolated in both directions.

Questions:

  1. Is this the expected picture roughly ten days after NU6.3 activation — i.e. is a large share of the network still on pre-Ironwood protocol versions?
  2. Is there published data on version distribution across the network? It would help operators judge whether a low peer count is local or systemic.
  3. Could the node’s own advertised address be excluded from the dial candidate set, rather than rejected at handshake time?

I’ve been running this node since spring without ever seeing peer counts this low. Happy to provide fuller logs or run diagnostics if useful.

1 Like

You should update to the latest zebra 6.2.3 and then see how it behaves.

Yes, i did, but look at the post above 4 days ago :
v6.2.3: “attempted to add a banned peer addr” logged ~300k times in 24h