1 Architecture
Claude edited this page 2026-02-20 15:12:17 +00:00

Architecture

Package Structure

go-blockchain/
  config/        Chain parameters (mainnet/testnet), hardfork schedule
  crypto/        CGo bridge to libcryptonote (ring sigs, BP+, Zarcanum, stealth)
  types/         Core data types: Block, Transaction, Address, KeyImage
  wire/          Binary serialisation (consensus-critical, bit-identical to C++)
  p2p/           Levin TCP protocol, peer discovery, handshake
  rpc/           Daemon and wallet JSON-RPC client + server
  chain/         Blockchain storage, block/tx validation, mempool
  wallet/        Key management, output scanning, tx construction
  difficulty/    PoW + PoS difficulty adjustment (LWMA variant)
  consensus/     Hardfork rules, block reward, fee policy

Dependency Diagram

                    +------------+
                    |  consensus |
                    +------+-----+
                           |
              +------------+------------+
              |                         |
        +-----+-----+            +-----+-----+
        |   chain    |            | difficulty |
        +-----+------+           +-----------+
              |
     +--------+---------+
     |        |         |
+----+--+ +---+---+ +---+---+
|  p2p  | |  rpc  | | wallet|
+----+--+ +---+---+ +---+---+
     |        |         |
     +--------+---------+
              |
         +----+----+
         |  wire   |
         +----+----+
              |
      +-------+-------+
      |               |
  +---+---+     +-----+-----+
  | types |     |   config   |
  +---+---+     +-----------+
      |
  +---+---+
  | crypto |  <-- CGo boundary
  +--------+

Key relationships

  • config and types are leaf packages with no internal dependencies (stdlib only).
  • wire depends on types for struct definitions and config for version-specific serialisation rules.
  • crypto wraps the C++ library via CGo; it is used by wire (for hashing), chain (for signature verification), and wallet (for key derivation and tx signing).
  • p2p, rpc, and wallet are higher-level packages that depend on wire-level serialisation.
  • chain is the central coordinator: it validates blocks using consensus rules, adjusts difficulty, and stores state.

CGo Bridge Boundary

The crypto/ package is the only package that crosses the CGo boundary. All other packages are pure Go.

Go side                          C++ side (libcryptonote)
+---------+                      +------------------------+
| crypto/ |  --- CGo calls --->  | cn_fast_hash()         |
|         |                      | generate_key_derivation|
|         |                      | derive_public_key      |
|         |                      | generate_key_image     |
|         |                      | check_ring_signature   |
|         |                      | CLSAG_GG_verify        |
|         |                      | CLSAG_GGX_verify       |
|         |                      | CLSAG_GGXXG_verify     |
|         |                      | bulletproof_plus_verify |
|         |                      | zarcanum_verify         |
|         |                      | chacha8_encrypt        |
+---------+                      +------------------------+

Build tags

The crypto package uses build tags to allow compilation without CGo for testing of non-crypto packages:

//go:build cgo

package crypto

When CGo is disabled, stub implementations return errors, allowing the rest of the codebase to compile and run tests that do not require real cryptographic operations.

Design Principles

  1. Consensus-critical code must be bit-identical to the C++ implementation. The wire/ package produces exactly the same binary output as the C++ serialisation for the same input.

  2. No global state. Chain parameters are passed via config.ChainConfig structs, not package-level globals. Mainnet and Testnet are pre-defined instances.

  3. Interfaces at boundaries. The chain/ package defines interfaces for storage backends, allowing LMDB, Pebble, or in-memory stores to be swapped.

  4. Test against real chain data. Wherever possible, tests use actual mainnet block and transaction hex blobs as test vectors, ensuring compatibility with the C++ node.