docs: Phase 3 P2P Levin protocol documentation

Co-Authored-By: Charon <charon@lethean.io>
This commit is contained in:
Claude 2026-02-20 19:45:28 +00:00
parent 412272b342
commit d33397e6b6
No known key found for this signature in database
GPG key ID: AF404715446AEB41
2 changed files with 99 additions and 4 deletions

View file

@ -17,6 +17,7 @@ types/ Core data types: Hash, PublicKey, Address, Block, Transaction
wire/ Binary serialisation (CryptoNote varint encoding)
difficulty/ PoW + PoS difficulty adjustment (LWMA variant)
crypto/ CGo bridge to vendored C++ libcryptonote (keys, signatures, proofs)
p2p/ CryptoNote P2P command types (handshake, sync, relay)
```
### config/
@ -81,6 +82,39 @@ LWMA (Linear Weighted Moving Average) difficulty adjustment algorithm for both
PoW and PoS blocks. Examines a window of recent block timestamps and cumulative
difficulties to calculate the next target difficulty.
### p2p/
CryptoNote P2P protocol command types for peer-to-peer communication. This
package provides encode/decode for all Levin protocol commands, built on the
`node/levin/` sub-package in go-p2p.
The package depends on `forge.lthn.ai/core/go-p2p/node/levin` for the Levin
wire format (33-byte header, portable storage serialisation, framed TCP
connections) and defines the application-level command semantics:
- **handshake.go** -- COMMAND_HANDSHAKE (1001): NodeData (network ID, peer ID,
local time, port) + CoreSyncData exchange. Peerlist decoding from packed
24-byte entries.
- **timedsync.go** -- COMMAND_TIMED_SYNC (1002): periodic blockchain state sync.
- **ping.go** -- COMMAND_PING (1003): simple liveness check.
- **relay.go** -- Block relay (2001), transaction relay (2002), chain
request/response (2006/2007).
- **sync.go** -- CoreSyncData type (current_height, top_id, checkpoint,
core_time, client_version, pruning mode).
- **commands.go** -- Command ID re-exports from the levin package.
- **integration_test.go** -- Build-tagged (`//go:build integration`) test that
TCP-connects to the C++ testnet daemon on localhost:46942 and performs a full
handshake + ping exchange.
The Levin wire format in go-p2p includes:
- **node/levin/header.go** -- 33-byte packed header with signature validation.
- **node/levin/varint.go** -- Portable storage varint (2-bit size mark, NOT the
same as CryptoNote LEB128 varints in wire/).
- **node/levin/storage.go** -- Portable storage section encode/decode (epee KV
format with 12 type tags).
- **node/levin/connection.go** -- Framed TCP connection with header + payload
read/write.
---
## Key Types

View file

@ -228,11 +228,72 @@ CryptoNote crypto library. The upstream code (37 files from Zano commit
All passing with `-race` and `go vet`.
## Phase 3 -- P2P Levin Protocol (Planned)
## Phase 3 -- P2P Levin Protocol
Implement the Levin binary protocol in `p2p/` for peer-to-peer communication.
Handshake, ping, timed sync, and block/transaction relay. Integrate with
`go-p2p` for connection management.
Phase 3 implemented the CryptoNote Levin binary protocol for peer-to-peer
communication across two repositories. The go-p2p package gained a `node/levin/`
sub-package with the wire format (header, portable storage, framed TCP
connection). The go-blockchain package gained a `p2p/` package with command
handlers for handshake, timed sync, ping, and block/transaction relay.
### Files added (go-p2p)
| File | Purpose |
|------|---------|
| `node/levin/header.go` | 33-byte Levin header encode/decode |
| `node/levin/header_test.go` | Header tests (9 tests) |
| `node/levin/varint.go` | Portable storage varint (2-bit size mark) |
| `node/levin/varint_test.go` | Varint tests (14 tests) |
| `node/levin/storage.go` | Portable storage section encode/decode |
| `node/levin/storage_test.go` | Storage tests (14 tests) |
| `node/levin/connection.go` | Framed TCP connection |
| `node/levin/connection_test.go` | Connection tests (7 tests) |
### Files added/modified (go-blockchain)
| File | Purpose |
|------|---------|
| `config/config.go` | Added NetworkID constants and ClientVersion |
| `config/config_test.go` | NetworkID validation test |
| `p2p/commands.go` | Command ID re-exports |
| `p2p/sync.go` | CoreSyncData type |
| `p2p/sync_test.go` | CoreSyncData roundtrip test |
| `p2p/ping.go` | Ping encode/decode |
| `p2p/ping_test.go` | Ping tests (2 tests) |
| `p2p/handshake.go` | Handshake command + NodeData + peerlist decoding |
| `p2p/handshake_test.go` | Handshake tests (4 tests) |
| `p2p/timedsync.go` | Timed sync request/response |
| `p2p/relay.go` | Block/tx relay + chain request/response |
| `p2p/relay_test.go` | Relay tests (6 tests) |
| `p2p/integration_test.go` | C++ testnet integration test |
### Key findings
- **Portable storage varint differs from CryptoNote varint.** CryptoNote uses
7-bit LEB128 (implemented in wire/varint.go). Portable storage uses a 2-bit
size mark in the low bits of the first byte (1/2/4/8 byte encoding). Both
implementations exist in separate packages.
- **POD-as-blob serialisation.** Hashes, network IDs, and other fixed-size types
are encoded as STRING values containing raw bytes, not as typed fields. The
peerlist is a single STRING blob containing packed 24-byte entries
(ip:4 + port:4 + id:8 + last_seen:8).
- **Network ID bytes from net_node.inl.** Mainnet: byte 10 = 0x00 (not testnet),
byte 15 = 0x54 (84 = formation version). Testnet: byte 10 = 0x01, byte 15 =
0x64 (100). These are validated during handshake.
- **P2P port is 46942, not 46941.** The testnet ports are: 46940 (stratum),
46941 (RPC), 46942 (P2P).
- **No Transport interface extraction.** The existing go-p2p WebSocket transport
is tightly coupled to WebSocket semantics. The Levin code lives in
`node/levin/` as a standalone sub-package rather than sharing an interface.
### Tests added
44 go-p2p tests + 13 go-blockchain p2p tests + 1 integration test = 58 total.
All passing with `-race` and `go vet`.
## Phase 4 -- RPC Layer (Planned)