Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
bitcoin-network
A low-level, Bitcoin Core–compatible network address library for Rust. It focuses on precise modelling of Bitcoin's internal network addressing, serialization, reachability, and bucketing logic, including full support for ADDRv1/ADDRv2 (BIP155) and overlay networks (Tor v3, I2P, CJDNS).
Overview
bitcoin-network provides a faithful Rust translation of Bitcoin Core's CNetAddr and associated logic. The crate is designed for systems that need to:
- Parse, normalise, and classify network endpoints used in the Bitcoin P2P layer.
- Support both legacy ADDRv1 and modern ADDRv2/BIP155 address encodings.
- Reason about reachability across IPv4, IPv6, Tor v3, I2P, CJDNS, and internal pseudo‑addresses.
- Compute peer grouping and AS‑based bucketing identifiers compatible with Core's AddrMan.
- Interoperate with existing Bitcoin ecosystem crates (
bitcoin-bitstream,bitcoin-hash,bitcoin-asmap,bitcoin-string, etc.).
The crate gives you the same semantics as Core for address validity, routability, reachability scoring, group identifiers, and overlay-encoding. This is essential if you want a Rust implementation to behave identically to Core peers on the public network.
Core Types
Network
Network classifies addresses into high-level network classes. These are used for:
- Reachability decisions (e.g. whether an address is considered publicly reachable).
- BIP155 network id mapping.
- AddrMan bucketing and group formation.
Semantics mirror Bitcoin Core exactly:
NET_UNROUTABLE– invalid / unroutable / placeholder.NET_IPV4,NET_IPV6– global IP networks.NET_ONION– Tor v3.onionservices.NET_I2P– I2P.b32.i2pdestinations.NET_CJDNS– CJDNS addresses (must start with0xfc).NET_INTERNAL– pseudo‑addresses used by AddrMan for DNS seeds, internal bookkeeping, etc.NET_MAX– sentinel (not a real network, used for sizing / iteration bounds in Core).
BIP155Network
Internal representation of BIP155 network ids. TORv2 is kept only to validate/ignore legacy payloads; the crate enforces TORv3 addresses for new encodings.
NetAddr
NetAddr represents a single network address in the sense of Bitcoin Core:
addrholds the raw address bytes. Its interpretation depends onnet.netis the high-levelNetworkclassification.scope_idis used for IPv6 scoped addresses (e.g. link‑local with an interface index).
The crate provides a large number of methods that match the C++ behaviour, including:
- Construction and conversion from
InAddr(IPv4) andIn6Addr(IPv6). - Parsing of Tor v3
.onionstrings and I2P.b32.i2pstrings. - Mapping and unmapping of IPv4⟷IPv6 embeddings (RFC6052, RFC6145, 6to4, Teredo).
- BIP155 (ADDRv2) serialization / deserialization.
- Legacy ADDRv1 serialization / deserialization.
- Validity, routability, and classification according to a wide range of IANA/IETF registry ranges (RFC1918, RFC3927, RFC4193, RFC5737, RFC3849, RFC4843, RFC7343, etc.).
- AS‑based mapping with an
asmapbitvector for AddrMan.
Features by Domain
1. Address Formatting Helpers
The crate contains helpers to render addresses to canonical string representations with the same rules as Core:
;
;
;
ipv4_to_stringrenders a 4‑octet IPv4 address asd.d.d.d.ipv6_to_stringusesstd::net::Ipv6Addrand yields RFC 5952–compliant compressed text forms, optionally with%scope_idsuffix.onion_to_stringcomputes the Tor v3 checksum and version, base32 encodes the 32‑byte public key and metadata, and appends.onion.
2. BIP155 / ADDRv2 Support
NetAddr can serialize and unserialize itself in both legacy ADDRv1 and modern ADDRv2 forms:
serialize and unserialize automatically choose between v1 and v2 based on the stream's version flag (ADDRV2_FORMAT bit), exactly matching Core's feature gating. This makes the crate safe to use in mixed-version networks and when persisting AddrMan on disk.
The mapping between Network and BIP155Network is handled by:
Unknown future ids are ignored (payload skipped), while mismatched founding ids trigger panics, mimicking Core's behaviour.
3. Validity, Routability, and Reachability
The crate encodes all of Core's validity and routing heuristics:
This allows you to reason at the same level of granularity as Core about whether an address should be gossiped, connected to, or deprioritised.
Reachability Metrics
NetAddr exposes the same integer reachability scale that Core uses in outbound peer selection and connection policy:
The metric differentiates between:
- Direct IPv4↔IPv4 reachability.
- Native IPv6 vs. tunneled IPv6 (6to4, Teredo, etc.).
- Overlay networks (Tor, I2P) with special cases for private communication.
The helper trait CheckIsReachable provides a higher‑level boolean classification:
Currently Network::is_reachable() is a placeholder mirroring Core's vfLimited gating.
4. Overlay Parsing: Tor and I2P
To correctly support overlay networks, NetAddr can parse and validate textual Tor/I2P destinations:
Tor v3 handling matches spec:
- Parses
*.onionhostnames. - Base32‑decodes payload without padding.
- Splits into
PUBKEY | CHECKSUM | VERSION. - Verifies version byte.
- Recomputes checksum as
SHA3_256(b".onion checksum" || PUBKEY || VERSION)[0..2]and compares.
I2P handling similarly enforces the 52-char base32 + .b32.i2p suffix, then decodes via the shared bitcoin_string utilities.
5. IPv4/IPv6 Embeddings and Legacy Encodings
NetAddr provides precise handling of IPv4 mapped and translated addresses as used in legacy encodings and in IPv6 transition mechanisms:
set_legacy_ipv6decodes embedded IPv4, INTERNAL, and deprecated TORv2 prefixes into the appropriateNetworkvariant and canonicaladdrbytes.has_linked_ipv4andget_linked_ipv4reconstruct the equivalent IPv4 address from IPv6 forms (6to4, SIIT translated, Teredo, etc.), always in network byte order.is_addr_v1compatibletests whether the address can be encoded in ADDRv1 (NET_IPV4,NET_IPV6,NET_INTERNAL).
6. AS‑based Bucketing and Grouping
For peer selection and sybil resistance, Core uses an AS map (asmap) and group identifiers. This crate reproduces that behaviour exactly:
get_mappedasinterprets the IP as a 128‑bit bitstring, then usesbitcoin_asmap::interpretto map into an autonomous system number. If there is no mapping (orasmapis empty, or the address is non‑IPv4/IPv6), it returns0, which is reserved by RFC7607.get_groupuses either the AS mapping or network‑specific prefix rules to return a canonical byte vector representing the address group. No two outbound connections are attempted to addresses with the same group, mirroring Core's design:- IPv4: /16 prefix buckets.
- IPv6: /32 or /36 for HE.net, depending on address.
- Tor/I2P/CJDNS: /4 prefix in their overlay space.
- Internal: full 10‑byte prefix.
- Local & unroutable: single shared group by network class.
7. Hashing and Byte Representation
For indexing and deduplication, NetAddr provides deterministic, Core‑compatible hashing and raw byte extraction:
get_addr_bytesreturns either the legacy ADDRv1 16‑byte representation or the rawaddrpayload, depending onis_addr_v1compatible.get_hashcomputes a 256‑bit hash (bitcoin_hash::hash1, double‑SHA256‑style) over the raw address bytes and returns the first 64 bits in little‑endian order as au64, following Core's conventions.
Example Usage
Creating and Formatting Addresses
use ;
Serializing with ADDRv2 / BIP155
use NetAddr;
use ;
const ADDRV2_FORMAT: u32 = 1 << 31; // Example feature bit; use the same as in your stack.
Using AS Maps for Grouping
use NetAddr;
Algorithmic and Standards Background
The crate embeds a substantial amount of network‑theoretic and protocol knowledge:
- BIP155 / ADDRv2: variable‑length address payloads tagged with network ids, enabling extensible support for non‑IP overlays without abusing IPv6 space.
- IPv6 Text Representation: RFC 5952 mandates canonical zero compression and lowercase hex; using
std::net::Ipv6Addrensures consistent formatting. - Transition Mechanisms: 6to4 (RFC3964), Teredo (RFC4380), IPv4‑embedded formats (RFC6052, RFC6145), autoconfiguration (RFC4862) are used in reachability classification.
- Private and Documentation Ranges: RFC1918, RFC3927, RFC5737, RFC3849, RFC4193, RFC4843, RFC7343 are explicitly vetted in
is_validandis_routable. - Autonomous System Mapping:
asmapis a compressed DFA over IP bits.get_mappedasbuilds a 128‑bit boolean vector representation and feeds it intobitcoin_asmap::interpret, which yields a stable AS number used for bucket diversification.
This crate effectively exports the same policy surface that Core uses, allowing you to replicate its peer selection and address management logic precisely in Rust.
Safety and Panics
Many methods are designed under the assumption of internal invariants, just as in Core:
- Several functions
assert!on address length (e.g., IPv4 must be 4 bytes, IPv6 must be 16 bytes, Tor v3 must be 32 bytes, etc.). - Certain misconfigurations (e.g. founding BIP155 ids with incorrect payload sizes,
NET_UNROUTABLE/NET_MAXused as actual network types) panic. - Pointer‑based APIs (
get_in_addr,get_in_6addr,get_reachability_from) useunsafeand assume the caller provides valid pointers.
This is intentional: the crate is engineered as a near drop‑in for Core internals, and invalid data is expected to be filtered or asserted away earlier in the call chain.
Integration Notes
- Rust Edition: 2021.
- License: MIT.
- Repository: https://github.com/klebs6/bitcoin-rs
- Intended Consumers: implementers of Bitcoin P2P stacks, alternative full node implementations, network simulators, asmap tooling, and research systems requiring bit‑exact compatibility with Bitcoin Core's address handling.
To use the crate in your project:
[]
= "0.1.19"
Then import the relevant items:
use ;
If you integrate with other bitcoin-rs components, the dependency set and versions should be aligned with the bitcoin-rs workspace for maximum compatibility.