Skip to content

feat(foundations): migrate ADNL documentation#2052

Open
coalus wants to merge 3 commits intoton-org:mainfrom
coalus:feat/adnl-migration
Open

feat(foundations): migrate ADNL documentation#2052
coalus wants to merge 3 commits intoton-org:mainfrom
coalus:feat/adnl-migration

Conversation

@coalus
Copy link
Copy Markdown
Contributor

@coalus coalus commented Apr 3, 2026

resolves #1035

Summary by CodeRabbit

  • Documentation
    • Added comprehensive ADNL (Abstract Datagram Network Layer) documentation covering protocol overview, address/key concepts, and security notes
    • Published separate guides for ADNL over TCP and ADNL over UDP with connection, packet, and channel behaviors
    • Reorganized network protocol docs under a new "Blockchain foundations" group
    • Updated legacy documentation redirects to point to the new foundation pages

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 3, 2026

Skipping AI review because this PR is from a fork. A maintainer can start the review by commenting /review in this PR.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 3, 2026

📝 Walkthrough

Walkthrough

Adds a new "Network protocols" navigation group and redirects in docs.json, and introduces three new documentation pages under foundations/network/ describing ADNL overview, ADNL over TCP, and ADNL over UDP.

Changes

Cohort / File(s) Summary
Docs navigation & redirects
docs.json
Added "Network protocols" group under "Blockchain foundations" linking new ADNL pages; updated legacy ADNL redirect entries to point to the new foundation pages.
ADNL overview page
foundations/network/adnl.mdx
New overview of ADNL: address derivation, key types, neighbor tables, high-level TCP/UDP behaviors, handshake and per-datagram formats, security notes, and cross-links.
ADNL over TCP
foundations/network/adnl-tcp.mdx
New TCP-specific doc: handshake sequence, 160-byte session params, AES-CTR encryption and checksum rules, ADNL packet format, liteserver query/response wrapping, TL schemas and examples, and key ID rules.
ADNL over UDP
foundations/network/adnl-udp.mdx
New UDP-specific doc: initial createChannel/query flow, packet signing/encryption, ECDH-derived channel keys, per-channel packet format, chunking/custom messages, and related links.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I nibble notes by moonlit log,
Docs hop home from the old analogue,
TCP, UDP — three pages sprout,
New paths point where knowledge's about,
A tiny hop for a rabbit's cheer!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Linked Issues check ❓ Inconclusive The PR addresses most objectives from #1035: provides ADNL description, explains how it works, documents TCP/UDP protocols, and migrates documentation. However, public/private overlays are not explicitly documented. Verify whether public and private overlays documentation (#1035 requirement) should be included, or confirm this requirement is outside the current PR scope.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change—migrating ADNL documentation to the foundations section—and aligns with the primary objective of the PR.
Out of Scope Changes check ✅ Passed All changes are directly related to ADNL documentation migration. Configuration changes in docs.json (redirects and navigation) are supporting infrastructure for the new documentation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
foundations/network/adnl-udp.mdx (1)

9-11: Prefer docs-owned routes for the DHT/RLDP links.

Lines 9-11 and 181-188 hardcode old-docs.ton.org for related protocol links. docs.json already owns redirects for those topics, so these should point to the site-local routes instead; that keeps users on docs.ton.org and avoids another content edit when DHT/RLDP are migrated.

🔗 Suggested link cleanup
- ADNL over UDP is the protocol used by TON nodes to communicate with each other. It serves as the foundation for higher-level protocols such as [DHT](https://old-docs.ton.org/v3/documentation/network/protocols/dht/overview) and [RLDP](https://old-docs.ton.org/v3/documentation/network/protocols/rldp).
+ ADNL over UDP is the protocol used by TON nodes to communicate with each other. It serves as the foundation for higher-level protocols such as [DHT](/v3/documentation/network/protocols/dht/overview) and [RLDP](/v3/documentation/network/protocols/rldp).

Apply the same replacement in the See also list.

Also applies to: 181-188

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@foundations/network/adnl-udp.mdx` around lines 9 - 11, Replace hardcoded
external links to "https://old-docs.ton.org/..." with the site-local routes
defined in docs.json for the DHT and RLDP pages in the ADNL over UDP doc: update
the two inline links that currently point to the DHT and RLDP old-docs URLs (the
ones used in the paragraph contrasting ADNL over UDP and ADNL over TCP) and the
same two entries in the "See also" list to use the local route paths (e.g., the
canonical /foundations/... or /network/... routes managed by docs.json) so the
links remain on docs.ton.org and follow existing redirects.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs.json`:
- Around line 1400-1401: The redirect entry mapping "source":
"/v3/documentation/network/protocols/adnl/low-level" currently points to the
generic overview; update its "destination" to the migrated deep-dive path
"/foundations/network/adnl-udp" so legacy deep links resolve to the
low-level/channel material, and ensure the chained redirect for
"/learn/networking/low-level-adnl" (if present elsewhere) also targets
"/foundations/network/adnl-udp" to keep both redirects consistent.

In `@foundations/network/adnl-tcp.mdx`:
- Around line 55-57: Update the hyperlink target so the sentence "Data is
serialized using [TL]" points to the TL overview, not the TL‑B overview: change
the link in the ADNL TCP handshake paragraph (the
"[TL](/languages/tl-b/overview)" occurrence in foundations/network/adnl-tcp.mdx)
to the TL overview URL (for example "/languages/tl/overview") so implementers
are directed to the correct serialization format.

In `@foundations/network/adnl.mdx`:
- Around line 9-124: The ADNL overview omits definitions for "public/private
overlays" and "ADNL forks" referenced by issue `#1035`; add a short dedicated
subsection (e.g., "## Overlays and ADNL forks") that: defines public vs private
overlays, explains how ADNL forks occur and their effect on peer
discovery/neighbour tables, and links to any migrated detailed pages or the
original issue for full specs; place this subsection near "Neighbor tables" or
before "P2P protocol (ADNL over UDP)" and reference existing pages like "ADNL
TCP" / "ADNL UDP" for examples so readers can follow up.
- Around line 67-73: The byte-range notation for deriving AES key/nonce from
secret and hash is ambiguous; update the descriptions around
SHA-256(aes_params), key and nonce so they use explicit half-open ranges or byte
counts (e.g., secret[0..16) meaning bytes 0–15, hash[16..32) meaning bytes
16–31) and state resulting lengths (key = 32 bytes, nonce = 12 bytes), and make
the identical change in the TCP page copy; reference the symbols `secret`, `hash
= SHA-256(aes_params)`, `key` and `nonce` so the two occurrences are updated
consistently.

---

Nitpick comments:
In `@foundations/network/adnl-udp.mdx`:
- Around line 9-11: Replace hardcoded external links to
"https://old-docs.ton.org/..." with the site-local routes defined in docs.json
for the DHT and RLDP pages in the ADNL over UDP doc: update the two inline links
that currently point to the DHT and RLDP old-docs URLs (the ones used in the
paragraph contrasting ADNL over UDP and ADNL over TCP) and the same two entries
in the "See also" list to use the local route paths (e.g., the canonical
/foundations/... or /network/... routes managed by docs.json) so the links
remain on docs.ton.org and follow existing redirects.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f54e7dd6-96e0-46f0-986e-be6ab7bbfb1f

📥 Commits

Reviewing files that changed from the base of the PR and between c9da5b6 and 22da021.

📒 Files selected for processing (4)
  • docs.json
  • foundations/network/adnl-tcp.mdx
  • foundations/network/adnl-udp.mdx
  • foundations/network/adnl.mdx

Comment on lines 1400 to +1401
"source": "/v3/documentation/network/protocols/adnl/low-level",
"destination": "https://old-docs.ton.org/v3/documentation/network/protocols/adnl/low-level",
"destination": "/foundations/network/adnl",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Route the legacy low-level ADNL URL to the UDP page.

/v3/documentation/network/protocols/adnl/low-level was the old deep-dive entry, but Line 1401 now sends it to the generic overview. The migrated low-level/channel material lives in /foundations/network/adnl-udp, so existing deep links lose the implementation details they used to surface. /learn/networking/low-level-adnl inherits the same mismatch through the chained redirect.

🔀 Suggested redirect fix
     {
       "source": "/v3/documentation/network/protocols/adnl/low-level",
-      "destination": "/foundations/network/adnl",
+      "destination": "/foundations/network/adnl-udp",
       "permanent": true
     },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"source": "/v3/documentation/network/protocols/adnl/low-level",
"destination": "https://old-docs.ton.org/v3/documentation/network/protocols/adnl/low-level",
"destination": "/foundations/network/adnl",
"source": "/v3/documentation/network/protocols/adnl/low-level",
"destination": "/foundations/network/adnl-udp",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs.json` around lines 1400 - 1401, The redirect entry mapping "source":
"/v3/documentation/network/protocols/adnl/low-level" currently points to the
generic overview; update its "destination" to the migrated deep-dive path
"/foundations/network/adnl-udp" so legacy deep links resolve to the
low-level/channel material, and ensure the chained redirect for
"/learn/networking/low-level-adnl" (if present elsewhere) also targets
"/foundations/network/adnl-udp" to keep both redirects consistent.

Comment on lines +9 to +124
The Abstract Datagram Network Layer (ADNL) is the core networking protocol of the TON network. It is a peer-to-peer, unreliable datagram protocol that operates over both UDP and TCP.

Higher-level protocols such as [RLDP](https://old-docs.ton.org/v3/documentation/network/protocols/rldp) and [DHT](https://old-docs.ton.org/v3/documentation/network/protocols/dht/overview) are built on top of ADNL.

## ADNL address

Each participant in the network has a 256-bit ADNL address. ADNL allows sending and receiving datagrams using only these addresses, hiding the underlying IP addresses and ports.

An ADNL address is derived as:

```text
address = SHA-256(type_id || public_key)
```

where `type_id` is a little-endian uint32 indicating the key type (the TL-serialized key object ID). The corresponding private key must be known to receive and decrypt messages sent to a given address.

## Public-key cryptosystems

| `type_id` | Cryptosystem |
| ------------ | ------------ |
| `0x4813b4c6` | ed25519 |

<Aside type="note">
To perform x25519, the keypair must be generated in x25519 format. The public key is transmitted over the network in ed25519 format, so conversion from x25519 to ed25519 is required. See [this example](https://github.com/andreypfau/curve25519-kotlin/blob/f008dbc2c0ebc3ed6ca5d3251ffb7cf48edc91e2/src/commonMain/kotlin/curve25519/MontgomeryPoint.kt#L39) for Kotlin.
</Aside>

## Peer identity

Each peer must have at least one identity, consisting of a keypair for the Diffie-Hellman exchange. An abstract network address is derived from the public key as described above.

## Encryption and security

ADNL packets can be signed and encrypted. When signatures are present, recipients verify integrity and authenticity.

## Neighbor tables

A TON ADNL node maintains a _neighbor table_ containing information about known nodes: their abstract addresses, public keys, IP addresses, and UDP ports. The table is updated over time as new entries are discovered from query responses and outdated records are removed.

## Client-server protocol (ADNL over TCP)

The client connects to the server using TCP and sends a handshake packet containing a server abstract address, a client public key, and encrypted AES-CTR session parameters.

### Handshake

1. The client performs a key agreement protocol (x25519) using its private key and the server's public key to derive a `secret`.

1. The client generates AES-CTR session parameters (16-byte nonce and 32-byte key for both transmit and receive directions) and serializes them into a 160-byte buffer:

| Parameter | Size |
| ---------- | -------- |
| `rx_key` | 32 bytes |
| `tx_key` | 32 bytes |
| `rx_nonce` | 16 bytes |
| `tx_nonce` | 16 bytes |
| `padding` | 64 bytes |

Fill the entire 160-byte buffer with random bytes. Otherwise, an attacker may perform an active man-in-the-middle attack using compromised AES-CTR session parameters.

1. The client encrypts the session parameters using AES-256-CTR with a key and nonce derived from the `secret` and the SHA-256 hash of the parameters:

```cpp
hash = SHA-256(aes_params)
key = secret[0..16] || hash[16..32]
nonce = hash[0..4] || secret[20..32]
```

1. The client sends the 256-byte handshake packet:

| Parameter | Size | Description |
| --------------------- | --------- | ------------------------------------- |
| `receiver_address` | 32 bytes | Server peer identity |
| `sender_public` | 32 bytes | Client public key |
| `SHA-256(aes_params)` | 32 bytes | Integrity proof of session parameters |
| `E(aes_params)` | 160 bytes | Encrypted session parameters |

1. The server decrypts the session parameters and verifies:

- It possesses the private key for `receiver_address`.
- `SHA-256(aes_params) == SHA-256(D(E(aes_params)))`.

If any check fails, the server drops the connection. If all checks pass, the server sends an empty datagram to prove private key ownership.

### Datagram

Both sides initialize two AES-CTR instances (transmit and receive) using the session parameters from the handshake.

Each datagram has the following structure:

| Parameter | Size | Description |
| --------- | ----------------------- | ------------------------------------------- |
| `length` | 4 bytes (little-endian) | Total datagram length, excluding this field |
| `nonce` | 32 bytes | Random value |
| `buffer` | `length - 64` bytes | Payload |
| `hash` | 32 bytes | `SHA-256(nonce \|\| buffer)` for integrity |

The entire structure is encrypted using the corresponding AES-CTR instance. The receiver decrypts the first 4 bytes to get the length, reads exactly that many bytes, and verifies the hash. On failure, the connection must be dropped.

The first datagram always goes from the server to the client after a successful handshake, with an empty buffer.

For practical examples of ADNL over TCP, including liteserver communication, ping/pong, and smart contract method calls, see [ADNL TCP](/foundations/network/adnl-tcp).

### Security considerations

**Handshake padding**: The 64-byte padding field in the handshake is unused by current implementations. It may have been intended to support future migration to alternative encryption primitives.

**Session key derivation**: The encryption key is derived from both the static `secret` and `SHA-256(aes_params)`. Since `aes_params` is random per session, this ensures a unique encryption key for each connection. However, the concatenation-based key derivation algorithm (mixing subarrays of secret and hash) is considered suboptimal by modern standards.

**Datagram nonce**: In CTR mode, AES functions as a stream cipher, making bit-flipping attacks possible if an attacker knows the plaintext. The nonce field prevents this: even if an attacker can reconstruct the key stream and compute a valid `SHA-256(buffer)`, they cannot forge the hash without knowing the random nonce.

## P2P protocol (ADNL over UDP)

In the UDP variant, the connection is established simultaneously with sending initial data. If the initiator sends a _create channel_ message, a channel key is calculated and creation is confirmed by the peer.

Unlike TCP, the UDP implementation uses channels for ongoing communication. Encryption keys are derived from the client's private key and the peer's public key (known from configuration or discovered from other nodes).

For the full protocol walkthrough with packet examples, see [ADNL UDP](/foundations/network/adnl-udp).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

The migration still omits overlays and ADNL fork behavior.

Issue #1035 explicitly calls out public/private overlays and ADNL forks, but this overview never defines those concepts or links to a migrated replacement. As merged, the new foundations section still leaves part of the promised ADNL coverage behind.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@foundations/network/adnl.mdx` around lines 9 - 124, The ADNL overview omits
definitions for "public/private overlays" and "ADNL forks" referenced by issue
`#1035`; add a short dedicated subsection (e.g., "## Overlays and ADNL forks")
that: defines public vs private overlays, explains how ADNL forks occur and
their effect on peer discovery/neighbour tables, and links to any migrated
detailed pages or the original issue for full specs; place this subsection near
"Neighbor tables" or before "P2P protocol (ADNL over UDP)" and reference
existing pages like "ADNL TCP" / "ADNL UDP" for examples so readers can follow
up.

Comment on lines +67 to +73
1. The client encrypts the session parameters using AES-256-CTR with a key and nonce derived from the `secret` and the SHA-256 hash of the parameters:

```cpp
hash = SHA-256(aes_params)
key = secret[0..16] || hash[16..32]
nonce = hash[0..4] || secret[20..32]
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Make the handshake byte ranges unambiguous.

Lines 71-72 use 0..16 / 16..32 notation without saying whether the end index is inclusive. If a reader treats those literally, the derived AES key/nonce lengths are wrong. Please spell these as half-open ranges or explicit byte counts. The TCP page repeats the same formula later, so both copies should use the same notation.

🧮 Suggested notation fix
-   hash = SHA-256(aes_params)
-   key = secret[0..16] || hash[16..32]
-   nonce = hash[0..4] || secret[20..32]
+   hash = SHA-256(aes_params)
+   key = secret[0..16) || hash[16..32)
+   nonce = hash[0..4) || secret[20..32)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@foundations/network/adnl.mdx` around lines 67 - 73, The byte-range notation
for deriving AES key/nonce from secret and hash is ambiguous; update the
descriptions around SHA-256(aes_params), key and nonce so they use explicit
half-open ranges or byte counts (e.g., secret[0..16) meaning bytes 0–15,
hash[16..32) meaning bytes 16–31) and state resulting lengths (key = 32 bytes,
nonce = 12 bytes), and make the identical change in the TCP page copy; reference
the symbols `secret`, `hash = SHA-256(aes_params)`, `key` and `nonce` so the two
occurrences are updated consistently.

@coalus coalus requested a review from a team as a code owner April 3, 2026 06:39
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
foundations/network/adnl-tcp.mdx (1)

57-57: Prefer internal TL docs link for consistency and longevity.

Line 57 points to core.telegram.org. Consider linking to your internal TL docs page so navigation stays in-repo and less sensitive to external URL drift.

Suggested fix
-After this exchange the connection is established. Data is serialized using [TL (Type Language)](https://core.telegram.org/mtproto/TL).
+After this exchange the connection is established. Data is serialized using [TL (Type Language)](/languages/tl/overview).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@foundations/network/adnl-tcp.mdx` at line 57, Replace the external
core.telegram.org link used in the sentence "Data is serialized using [TL (Type
Language)](https://core.telegram.org/mtproto/TL)" with the project's internal TL
documentation page to ensure link stability; update the Markdown link target
while keeping the link text "TL (Type Language)" unchanged so references to TL
remain consistent across the repo (edit the adnl-tcp.mdx line containing that
link).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@foundations/network/adnl-tcp.mdx`:
- Around line 136-138: The schema block is labeled as "tlb" but is a TL schema;
update the code fence label from tlb to tl for the snippet containing
liteServer.runSmcMethod (the line starting with "liteServer.runSmcMethod mode:#
... = liteServer.RunMethodResult") so syntax highlighting and reader
expectations match the TL grammar.

---

Nitpick comments:
In `@foundations/network/adnl-tcp.mdx`:
- Line 57: Replace the external core.telegram.org link used in the sentence
"Data is serialized using [TL (Type
Language)](https://core.telegram.org/mtproto/TL)" with the project's internal TL
documentation page to ensure link stability; update the Markdown link target
while keeping the link text "TL (Type Language)" unchanged so references to TL
remain consistent across the repo (edit the adnl-tcp.mdx line containing that
link).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 51423583-f7f6-4a66-8d58-5d093dd14f14

📥 Commits

Reviewing files that changed from the base of the PR and between 22da021 and c3f159c.

📒 Files selected for processing (2)
  • foundations/network/adnl-tcp.mdx
  • foundations/network/adnl.mdx
✅ Files skipped from review due to trivial changes (1)
  • foundations/network/adnl.mdx

Comment on lines +136 to +138
```tlb
liteServer.runSmcMethod mode:# id:tonNode.blockIdExt account:liteServer.accountId method_id:long params:bytes = liteServer.RunMethodResult
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use tl instead of tlb for this schema block.

Line 136 labels the snippet as tlb, but liteServer.runSmcMethod ... is a TL schema, not TL-B. This can mislead readers and syntax highlighting.

Suggested fix
-```tlb
+```tl
 liteServer.runSmcMethod mode:# id:tonNode.blockIdExt account:liteServer.accountId method_id:long params:bytes = liteServer.RunMethodResult
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@foundations/network/adnl-tcp.mdx` around lines 136 - 138, The schema block is
labeled as "tlb" but is a TL schema; update the code fence label from tlb to tl
for the snippet containing liteServer.runSmcMethod (the line starting with
"liteServer.runSmcMethod mode:# ... = liteServer.RunMethodResult") so syntax
highlighting and reader expectations match the TL grammar.

@novusnota novusnota self-requested a review April 5, 2026 22:52
@novusnota novusnota requested a review from aigerimu April 7, 2026 08:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Foundations > Network] ADNL

2 participants