Files
simplexmq/contributing/CODE.md

3.9 KiB

Coding and building

This file provides guidance on coding style and approaches and on building the code.

Code Security

When designing code and planning implementations:

  • Apply adversarial thinking, and consider what may happen if one of the communicating parties is malicious.
  • Formulate an explicit threat model for each change - who can do which undesirable things and under which circumstances.

Code Style, Formatting and Approaches

The project uses fourmolu for Haskell code formatting. Configuration is in fourmolu.yaml.

Key formatting rules:

  • 2-space indentation
  • Trailing function arrows, commas, and import/export style
  • Record brace without space: {field = value}
  • Single newline between declarations
  • Never use unicode symbols
  • Inline let style with right-aligned in

Format code before committing:

# Format a single file
fourmolu -i src/Simplex/Messaging/Protocol.hs

Some files that use CPP language extension cannot be formatted as a whole, so individual code fragments need to be formatted.

Follow existing code patterns:

  • Match the style of surrounding code
  • Use qualified imports with short aliases (e.g., import qualified Data.ByteString.Char8 as B)
  • Use record syntax for types with multiple fields
  • Prefer explicit pattern matching over partial functions

Comments policy:

  • Avoid redundant comments that restate what the code already says
  • Only comment on non-obvious design decisions or tricky implementation details
  • Function names and type signatures should be self-documenting
  • Do not add comments like "wire format encoding" (Encoding class is always wire format) or "check if X" when the function name already says that
  • Assume a competent Haskell reader

Diff and refactoring:

  • Avoid unnecessary changes and code movements
  • Never do refactoring unless it substantially reduces cost of solving the current problem, including the cost of refactoring
  • Aim to minimize the code changes - do what is minimally required to solve users' problems

Document and code structure:

  • Never move existing code or sections around - add new content at appropriate locations without reorganizing existing structure.
  • When adding new sections to documents, continue the existing numbering scheme.
  • Minimize diff size - prefer small, targeted changes over reorganization.

Code analysis and review:

  • Trace data flows end-to-end: from origin, through storage/parameters, to consumption. Flag values that are discarded and reconstructed from partial data (e.g. extracted from a URI missing original fields) — this is usually a bug.
  • Read implementations of called functions, not just signatures — if duplication involves a called function, check whether decomposing it resolves the duplication.
  • Do not save time on analysis. Read every function in the data flow even when the interface seems clear — wrong assumptions about internals are the main source of missed bugs.

Haskell Extensions

  • StrictData enabled by default
  • Use STM for safe concurrency
  • Assume concurrency in PostgreSQL queries
  • Comprehensive warning flags with strict pattern matching

Build Commands

# Standard build
cabal build

# Fast build
cabal build --ghc-options -O0

# Build specific executables
cabal build exe:smp-server exe:xftp-server exe:ntf-server exe:xftp

# Build with PostgreSQL server support
cabal build -fserver_postgres

# Client-only library build (no server code)
cabal build -fclient_library

# Find binary location
cabal list-bin exe:smp-server

Cabal Flags

  • swift: Enable Swift JSON format
  • client_library: Build without server code
  • client_postgres: Use PostgreSQL instead of SQLite for agent persistence
  • server_postgres: PostgreSQL support for server queue/notification store

External Dependencies

Custom forks specified in cabal.project:

  • aeson, hs-socks (SimpleX forks)
  • direct-sqlcipher, sqlcipher-simple (encrypted SQLite)
  • warp, warp-tls (HTTP server)