Overview
Firedancer is a from-scratch validator client for Solana, designed to be fast, secure, and independent. This guide covers the code style conventions and development practices used throughout the project.The code style is defined by the code in
src/tango. Most contributors do not use automated code formatting tools.Getting Started
Firedancer currently only supports Linux and requires at least kernel v4.18 to build.Code Style Guide
General Conventions
Text Word Wrap
Aspire to word wrap text (comments, not code) at 72 columns for readability. This is the level the publishing industry has used for hundreds of years for making print easily readable with minimal eye strain.File Extensions
| Extension | File Type |
|---|---|
.c | Standalone C translation unit |
.h | Reusable C include file, no symbol defs (header) |
.c | Include-once C file, with symbol defs |
.s | Assembly files |
| (none) | Shell scripts |
Include Guards
Header files must use#ifndef include guards, not #pragma once.
Given file: src/path/to/file/fd_file_name.h:
Vertical Alignment
Unlike popular code formatting tools, Firedancer uses vertical alignment for better readability.
Spacing Rules
Function Calls
No spaces for function calls with zero arguments:sizeof:
Control Flow
Annotate uncommon error paths withFD_UNLIKELY.
For single-line if statements, no braces required:
Function Prototypes
- Modifiers and return types on separate lines
- One function argument per line
- Vertically align function argument types and names
Type System
Integers
Usefd_util_base.h types instead of stdint.h integer types:
| stdint | fd_util_base |
|---|---|
int8_t | schar |
uint8_t | uchar |
int16_t | short |
uint16_t | ushort |
int32_t | int |
uint32_t | uint |
int64_t | long |
ptrdiff_t | long |
uint64_t | ulong |
size_t | ulong |
Booleans
Do not usebool (stdbool). Instead use int.
The value 1 is “true” and the value 0 is “false”.
Function Documentation
- Documentation for a function is typically before the function prototype in a comment block
- Comments should mention the name of the function toward the beginning
- Function declarations belonging to a public API must be documented
- Implementations of these functions must not repeat the comment
Macros
These are recommendations. Depending on macro scope, these rules might not make sense.
Portability
Build Capabilities
Firedancer aspires to compile under any LP64 environment. If any component has more assumptions (e.g. needs a POSIX-like target), it should check for these capabilities via theFD_HAS_{...} switches.
Example Makefile:
Language Features
Try to stick to ISO C17. GNU C extensions are permitted as long as they are well supported by Clang and CBMC many years back.Compiler Compatibility
As of 2024-Jul, Firedancer builds on GNU/Linux sysroots with:- GCC 8.5 or newer
- Clang
- CBMC
fdctl) only targets x86_64 with a Haswell-like minimum feature set (AVX2, FMA).
Experimental support exists for:
- musl Linux, macOS, FreeBSD, Solana (SVM) C programs
- arm64, ppc64le, sBPFv1, sBPFv2
seccomp Sandbox
During initialization, a seccomp profile is installed to each tile containing rules for allowed syscalls. If a syscall is triggered unexpectedly, seccomp will crash Firedancer.File I/O
Preferfd_io over stdio.h for streaming file I/O. Make sure to handle EINTR correctly.
Security Best Practices
Fuzzing
Most code should be covered by fuzz tests. Try to:- Use graceful error handling instead of aborting/crashing/exiting
- Provide test APIs for mocking state (e.g. encryption keys when fuzzing a network protocol)
Test Vectors
Firedancer runs a large set of test vectors in CI that tests conformance between Firedancer and Agave’s block, transaction, instruction, and VM execution down to the same error code.Create test fixtures
Make a pull request into the test-vectors repository with your new fixtures. See solana-conformance for more information on generating fixtures.
Complex Function Exit
Sometimes complex control flow is unavoidable. A typical error is failure to release resources on variables that go out of scope. Instead of multiple return points, use ado/while scope:
cleanup attribute to execute an inline function when a variable goes out of scope. See FD_SCRATCH_SCOPE_BEGIN in src/util/scratch/fd_scratch.h for examples.