Awesome
<br/> <p align="center"> <h1 align="center"> ๐คโก <code>Sig</code> - a Solana Zig validator client</h1> <br/> <div align="center"> <a href="https://github.com/syndica/sig/releases/latest"><img alt="Version" src="https://img.shields.io/github/v/release/syndica/sig?include_prereleases&label=version"></a> <a href="https://github.com/syndica/sig/actions/workflows/check.yml"><img alt="Build status" src="https://img.shields.io/github/actions/workflow/status/syndica/sig/check.yml?branch=main" /></a> <a href="https://ziglang.org/download"><img alt="Zig" src="https://img.shields.io/badge/zig-0.13.0-green.svg"></a> <a href="https://github.com/syndica/sig/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/badge/license-Apache_2.0-blue.svg"></a> </div> </p> <br/>Sig is a Solana validator client implemented in Zig. Read the introductory blog post for more about the goals of this project. <br/> <br/>
โ ๏ธ NOTE: This is a WIP, please open any issues for any bugs/improvements.
File Structure
data/
โโ genesis-files/
โโ test-data/
docs/
โโ debugging.md
โโ fuzzing.md
โโ sig-cli.md
metrics
โโ prometheus/
โโ grafana/
scripts/
src/
โโ main.zig # exec entrypoint
โโ sig.zig # library entrypoint
โโ tests.zig
โโ fuzz.zig
โโ benchmarks.zig
๐ Setup
Build Dependencies
- Zig 0.13.0 - Choose one:
- Binary Releases (extract and add to PATH)
- Install with a package manager
- Manage multiple versions with zigup or zvm
Developer Tools</summary>
These tools are optional but recommended for a smooth development process.
- Zig Language Server (ZLS) 0.13.0
- lldb: Zig CLI Debugging
- Zig Language VS Code extension
- CodeLLDB VS Code extension
Visual Studio Code
If you use VS Code, you should install the Zig Language extension. It can use your installed versions of Zig and ZLS, or it can download and manage its own internal versions.
You can use CodeLLDB to debug Zig code with lldb in VS Code's debugging GUI. If you'd like to automatically build the project before running the debugger, you'll need a zig build
task.
{ ? // See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version"
: "2.0.0", "tasks": [{ "label": "zig build", "type": "shell", "command": "zig", "args": ["build", "--summary", "all"], "options": { "cwd": "${workspaceRoot}" }, "presentation": { "echo": true, "reveal": "always", "focus": false, "panel": "shared", "showReuseMessage": true, "clear": false }, "problemMatcher": [], "group": { "kind": "build", "isDefault": true } }] }
</details>
To run the debugger, you need a run configuration. This launch.json includes an example for debugging gossip. Customize the args as desired.
<details><summary>launch.json</summary>{
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug Gossip Mainnet",
"program": "${workspaceFolder}/zig-out/bin/sig",
"args": [
"gossip",
"--entrypoint",
"entrypoint.mainnet-beta.solana.com:8001",
"--entrypoint",
"entrypoint2.mainnet-beta.solana.com:8001",
"--entrypoint",
"entrypoint3.mainnet-beta.solana.com:8001",
"--entrypoint",
"entrypoint4.mainnet-beta.solana.com:8001",
"--entrypoint",
"entrypoint5.mainnet-beta.solana.com:8001"
],
"cwd": "${workspaceFolder}",
"preLaunchTask": "zig build"
}
]
}
</details>
</details>
๐ง Build
zig build
๐ Run
Run Sig with zig
or execute the binary you already built:
zig build run -- --help
./zig-out/bin/sig --help
These commands will be abbreviated as sig
in the rest of this document.
๐ค Identity
Sig stores its private key in ~/.sig/identity.key
. On its first run, Sig will automatically generate a key if no key exists. To see the public key, use the identity
subcommand.
sig identity
๐ Gossip
To run Sig as a Solana gossip client, use the gossip
subcommand. Specify entrypoints to connect to a cluster. Optionally use -p
to specify a custom listening port (default is 8001). For more info about gossip, see the readme.
sig gossip -p <PORT> --entrypoint <IP>:<PORT>
The following IP addresses were resolved from domains found at https://docs.solana.com/clusters.
<details><summary>mainnet</summary>sig gossip --entrypoint entrypoint.mainnet-beta.solana.com:8001 \
--entrypoint entrypoint2.mainnet-beta.solana.com:8001 \
--entrypoint entrypoint3.mainnet-beta.solana.com:8001 \
--entrypoint entrypoint4.mainnet-beta.solana.com:8001 \
--entrypoint entrypoint5.mainnet-beta.solana.com:8001
</details>
<details><summary>devnet</summary>
sig gossip --entrypoint entrypoint.devnet.solana.com:8001 \
--entrypoint entrypoint2.devnet.solana.com:8001 \
--entrypoint entrypoint3.devnet.solana.com:8001 \
--entrypoint entrypoint4.devnet.solana.com:8001 \
--entrypoint entrypoint5.devnet.solana.com:8001
</details>
<details><summary>testnet</summary>
sig gossip --entrypoint entrypoint.testnet.solana.com:8001 \
--entrypoint entrypoint2.testnet.solana.com:8001 \
--entrypoint entrypoint3.testnet.solana.com:8001
</details><br>
Develop
See Setup to get your environment set up. See CONTRIBUTING.md for the code style guide.
๐งช Test
Run all tests.
zig build test
Include --summary all
with any test command to see a summary of the test results.
Include a filter to limit which tests are run. Sig tests include their module name. For example, you can run all tests in gossip.table
like this:
zig build test --summary all -- gossip.table
๐ Benchmark
Run all benchmarks.
zig build benchmark
Run a benchmark group: socket_utils, gossip, or sync.
zig build benchmark -- gossip
<br>
๐ฆ Import Sig
Sig can be included as a dependency in your Zig project using build.zig.zon
file (available for Zig >= 0.12). See the API documentation to learn more about how to use Sig as a library.
-
Declare Sig as a dependency in
build.zig.zon
:.{ .name = "my-project", .version = "1.0.0", .dependencies = .{ + .sig = .{ + .url = "https://github.com/syndica/sig/archive/<COMMIT>.tar.gz", + }, }, }
-
Expose Sig as a module in
build.zig
:const std = @import("std"); pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); + const opts = .{ .target = target, .optimize = optimize }; + const sig_module = b.dependency("sig", opts).module("sig"); const exe = b.addExecutable(.{ .name = "test", .root_source_file = .{ .path = "src/main.zig" }, .target = target, .optimize = optimize, }); + exe.addModule("sig", sig_module); exe.install(); ... }
-
Obtain Sig's package hash:
$ zig build my-project/build.zig.zon:6:20: error: url field is missing corresponding hash field .url = "https://github.com/syndica/sig/archive/<COMMIT>.tar.gz", ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ note: expected .hash = "<HASH>",
-
Update
build.zig.zon
with hash value:
</details> <br>.{ .name = "my-project", .version = "1.0.0", .dependencies = .{ .sig = .{ .url = "https://github.com/syndica/sig/archive/<COMMIT>.tar.gz", + .hash = "<HASH>", }, }, }
๐ค Why Zig?
Zig's own definition: Zig is a general-purpose programming language and toolchain for maintaining robust, optimal and reusable software.
-
Optimized performance: Zig provides control over how your program runs at a low level, similar to languages like C. It allows fine-grained control over aspects such as memory management and system calls, which can lead to improved performance.
-
Safety focus: Zig has features built in to prevent common bugs and safety issues common in C. For example, it includes built-in testing and bounds checking, which can help avoid problems such as buffer overflows and undefined behavior.
-
Readability and maintainability: Zig syntax is designed to be straightforward and clear. This can make the code easier to understand, more maintainable, and less prone to bugs.
-
No hidden control flow: Zig doesn't allow hidden control-flow like exceptions in some other languages. This can make it easier to reason about what your program is doing.
-
Integration with C: Zig has excellent interoperation with C. You can directly include C libraries and headers in a Zig program, which can save time when using existing C libraries.
-
Custom allocators: Zig allows you to define custom memory allocation strategies for different parts of your program. This provides the flexibility to optimize memory usage for specific use-cases or workloads.
Note
- Zig is still an evolving language.
- Many of the low-level APIs have been stabilized but
std.http.Client
andstd.json
are still WIP targetting stable implementations by>=0.12
. - Currently,
std.http.Client
leaks and is failing some tests, fix is in works. <br><br>
๐งฉ Modules
-
Gossip - A gossip spy node, run by:
sig gossip
orzig build run -- gossip
-
Core - Core data structures shared across modules.
-
RPC Client (docs) - A fully featured HTTP RPC client with ability to query all on-chain data along with sending transactions. <br><br>
๐ Learn More
Sig