Home

Awesome

<br/> <p align="center"> <h1 align="center">&nbsp;๐Ÿค–โšก &nbsp;<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

<details><summary>

Developer Tools</summary>

These tools are optional but recommended for a smooth development process.

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.

<details><summary>tasks.json</summary>
{ ? // 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.

<details> <summary><code>Steps</code> - how to install Sig in your Zig project</summary>
  1. 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",
    +       },
        },
    }
    
  2. 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();
    
        ...
    }
    
  3. 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>",
    
  4. Update build.zig.zon with hash value:

    .{
        .name = "my-project",
        .version = "1.0.0",
        .dependencies = .{
            .sig = .{
                .url = "https://github.com/syndica/sig/archive/<COMMIT>.tar.gz",
    +           .hash = "<HASH>",
            },
        },
    }
    
    </details> <br>

๐Ÿค” Why Zig?

Zig's own definition: Zig is a general-purpose programming language and toolchain for maintaining robust, optimal and reusable software.

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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

๐Ÿงฉ Modules

๐Ÿ“š Learn More

Zig

Solana

Sig