Code Generation

Use protobuf code generation to integrate VeilNet with Python, JavaScript, or other languages. Start the Anchor subprocess and control it via gRPC.

Introduction

Official SDKs are available for Go. For Python, JavaScript/TypeScript, C#, Rust, Java, and other gRPC-capable languages, you can use protobuf code generation to build a VeilNet client that starts and controls the Anchor subprocess via gRPC. This guide walks you through generating client code and using it in your application.

Overview

VeilNet Conflux runs as a subprocess (the Anchor binary) that your application manages. Your app:

  1. Downloads the platform-specific Anchor binary from the conflux repository.
  2. Starts the binary as a subprocess.
  3. Connects to its gRPC server (typically on a local Unix socket or TCP port).
  4. Sends StartAnchor with your registration token so the Anchor joins the VeilNet overlay.
  5. Manages taints and lifecycle with AddTaint, RemoveTaint, StopAnchor, and related RPCs.

Note: The proto definitions and Anchor service are the same ones used by the Go SDK. Code generation gives you the same capabilities in any language that supports gRPC.

Prerequisites

Anchor Binaries

Download the appropriate binary for your OS and architecture from conflux/anchor/bin:

PlatformArchitectureBinary
LinuxAMD64anchor-linux-amd64
LinuxARM64anchor-linux-arm64
macOSAMD64anchor-darwin-amd64
macOSARM64 (Apple Silicon)anchor-darwin-arm64
WindowsAMD64anchor-windows-amd64.exe

After downloading, make the binary executable (Linux/macOS) and run it. The Anchor typically listens on a gRPC endpoint (port or Unix socket) that your application connects to.

Warning: The Anchor binary needs network administrator privileges to create a virtual network interface (TUN). On Linux, run with sudo or equivalent.

Proto Definitions

The proto file defines the Anchor gRPC service and all message types. Key definitions:

Anchor gRPC Service

service Anchor {
  rpc StartAnchor(StartAnchorRequest) returns (google.protobuf.Empty);
  rpc StartAnchorWithFD(StartAnchorWithFDRequest) returns (google.protobuf.Empty);
  rpc StopAnchor(google.protobuf.Empty) returns (google.protobuf.Empty);
  rpc AddTaint(AddTaintRequest) returns (google.protobuf.Empty);
  rpc RemoveTaint(RemoveTaintRequest) returns (google.protobuf.Empty);
  rpc GetInfo(google.protobuf.Empty) returns (GetInfoResponse);
  rpc GetRealmInfo(google.protobuf.Empty) returns (GetRealmInfoResponse);
  rpc GetVeilInfo(google.protobuf.Empty) returns (GetVeilInfoResponse);
  rpc GetTracerConfig(google.protobuf.Empty) returns (TracerConfig);
}

Main Request/Response Messages

MessagePurpose
StartAnchorRequestStart the Anchor with guardian_url, anchor_token, optional ip, rift, portal, tracer
AddTaintRequestAdd a taint label (e.g. web, api) for access control
RemoveTaintRequestRemove a taint label
GetInfoResponseNode id, tag, uid, cidr, rift, portal, public
GetRealmInfoResponserealm, realm_id, subnet
GetVeilInfoResponseveil_host, veil_port, region

For the full proto schema, see veilnet.proto in the conflux repository.

Python

Step 1: Generate gRPC Client Code

Install the protobuf compiler and gRPC tools:

pip install grpcio grpcio-tools

Download the proto file and generate Python code:

curl -o veilnet.proto https://raw.githubusercontent.com/veil-net/conflux/main/veilnet.proto
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. veilnet.proto

This creates veilnet_pb2.py (messages) and veilnet_pb2_grpc.py (service stubs). You will need google.protobuf; install it if needed:

pip install protobuf

Note: The proto imports google/protobuf/empty.proto. Ensure the protoc -I path includes the standard protobuf includes (e.g. via pip install protobuf and using the correct include path for your environment).

If grpc_tools.protoc cannot find google/protobuf/empty.proto, install the protobuf package and add its include path:

pip install protobuf
python -m grpc_tools.protoc -I. -I$(python -c "import google.protobuf; print(google.protobuf.__path__[0])") --python_out=. --grpc_python_out=. veilnet.proto

Step 2: Download and Start the Anchor Binary

import subprocess
import platform
import sys

def get_anchor_binary():
    """Return the Anchor binary filename for current platform."""
    system = platform.system().lower()
    machine = platform.machine().lower()
    if system == 'darwin':
        arch = 'arm64' if machine in ('arm64', 'aarch64') else 'amd64'
        return f'anchor-darwin-{arch}'
    if system == 'linux':
        arch = 'arm64' if machine in ('arm64', 'aarch64') else 'amd64'
        return f'anchor-linux-{arch}'
    if system == 'windows':
        return 'anchor-windows-amd64.exe'
    raise RuntimeError(f'Unsupported platform: {system}')

def start_anchor_process(anchor_path, args=None):
    """Start the Anchor binary as a subprocess."""
    cmd = [anchor_path] + (args or [])
    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    return proc

Step 3: Connect and Call the Anchor gRPC Service

import grpc
# Import your generated modules
# from veilnet_pb2 import StartAnchorRequest, AddTaintRequest
# from veilnet_pb2_grpc import AnchorStub

def main():
    # Anchor gRPC server listens on 127.0.0.1:1993 by default
    channel = grpc.insecure_channel('127.0.0.1:1993')
    stub = AnchorStub(channel)

    # Start the Anchor with your registration token
    request = StartAnchorRequest(
        guardian_url='https://guardian.veilnet.app',
        anchor_token='your-registration-token',
        ip='',  # Optional: leave empty for auto-assign
        rift=False,
        portal=False,
    )
    stub.StartAnchor(request)

    # Add taint for access control
    stub.AddTaint(AddTaintRequest(taint='web'))

    # Get node info
    info = stub.GetInfo(Empty())
    print(f'VeilNet IP: {info.cidr}')

    # When done: call stub.StopAnchor(Empty()) before terminating the subprocess

Replace your-registration-token with a token from your VeilNet console or Guardian API.

JavaScript / TypeScript

Step 1: Install Dependencies

npm install @grpc/grpc-js @grpc/proto-loader

Step 2: Load Proto and Create Client

Use @grpc/proto-loader to load the proto at runtime (no separate code generation step):

const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const path = require('path');

const packageDefinition = protoLoader.loadSync('veilnet.proto', {
  keepCase: true,
  longs: String,
  enums: String,
  defaults: true,
  oneofs: true,
});

const proto = grpc.loadPackageDefinition(packageDefinition).veilnet;
const client = new proto.Anchor('127.0.0.1:1993', grpc.credentials.createInsecure());

Step 3: Call the Anchor RPCs

// Start the Anchor
client.StartAnchor({
  guardian_url: 'https://guardian.veilnet.app',
  anchor_token: process.env.ANCHOR_TOKEN || 'your-registration-token',
  ip: '',
  rift: false,
  portal: false,
}, (err, response) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log('Anchor started');
});

// Add taint
client.AddTaint({ taint: 'api' }, (err) => {
  if (err) console.error(err);
});

// Get info
client.GetInfo({}, (err, info) => {
  if (err) console.error(err);
  else console.log('Node CIDR:', info.cidr);
});

With TypeScript

For better type safety, generate TypeScript definitions:

npm install -D grpc_tools_node_protoc_ts
# Or use protoc with protoc-gen-ts plugin

Alternatively, keep using @grpc/proto-loader and add manual type definitions for the loaded proto.

C# / .NET

Step 1: Create Project and Add Packages

dotnet new console -n VeilNetClient
cd VeilNetClient
dotnet add package Grpc.Net.Client
dotnet add package Google.Protobuf
dotnet add package Grpc.Tools

Step 2: Add Proto Reference

Download the proto and create a Protos folder:

mkdir -p Protos
curl -o Protos/veilnet.proto https://raw.githubusercontent.com/veil-net/conflux/main/veilnet.proto

Add the Google.Protobuf.Tools package or ensure google/protobuf/empty.proto is available. Edit your .csproj:

<ItemGroup>
  <Protobuf Include="Protos\veilnet.proto" GrpcServices="Client" ProtoRoot="Protos" />
</ItemGroup>

If the build fails on import "google/protobuf/empty.proto", add the Protobuf include path (e.g. from Google.Protobuf.Tools) or create Protos/google/protobuf/empty.proto from the protobuf repository.

Step 3: Connect and Call the Anchor Service

using Grpc.Net.Client;
using Grpc.Core;

// After building, use the generated client
// var channel = GrpcChannel.ForAddress("http://127.0.0.1:1993");
// var client = new Anchor.AnchorClient(channel);

// await client.StartAnchorAsync(new StartAnchorRequest
// {
//     GuardianUrl = "https://guardian.veilnet.app",
//     AnchorToken = "your-registration-token",
//     Ip = "",
//     Rift = false,
//     Portal = false,
// });

// await client.AddTaintAsync(new AddTaintRequest { Taint = "web" });
// var info = await client.GetInfoAsync(new Empty());
// Console.WriteLine($"VeilNet IP: {info.Cidr}");

// When done: await client.StopAnchorAsync(new Empty());

Rust

Step 1: Add Dependencies

Add to Cargo.toml:

[dependencies]
tonic = "0.12"
prost = "0.13"
[build-dependencies]
tonic-build = "0.12"

Step 2: Generate Client in build.rs

// build.rs
fn main() -> Result<(), Box<dyn std::error::Error>> {
    tonic_build::configure()
        .build_server(false)
        .compile(&["veilnet.proto"], &["."])?;
    Ok(())
}

Download the proto and ensure google/protobuf/empty.proto is available (e.g. from protobuf crate or prost-build includes).

Step 3: Use the Generated Client

use tonic::transport::Channel;

// let channel = Channel::from_static("http://127.0.0.1:1993").connect().await?;
// let mut client = anchor_client::AnchorClient::new(channel);

// client.start_anchor(StartAnchorRequest {
//     guardian_url: "https://guardian.veilnet.app".into(),
//     anchor_token: "your-registration-token".into(),
//     ip: String::new(),
//     rift: false,
//     portal: false,
//     tracer: None,
// }).await?;

// client.add_taint(AddTaintRequest { taint: "web".into() }).await?;
// let info = client.get_info(Empty {}).await?;
// println!("VeilNet IP: {}", info.into_inner().cidr);

// When done: client.stop_anchor(Empty {}).await?;

Java

Step 1: Add Maven Dependencies

<dependencies>
  <dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-netty-shaded</artifactId>
    <version>1.60.0</version>
  </dependency>
  <dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-protobuf</artifactId>
    <version>1.60.0</version>
  </dependency>
  <dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-stub</artifactId>
    <version>1.60.0</version>
  </dependency>
</dependencies>

<build>
  <extensions>
    <extension>
      <groupId>kr.motd.maven</groupId>
      <artifactId>os-maven-plugin</artifactId>
      <version>1.7.1</version>
    </extension>
  </extensions>
  <plugins>
    <plugin>
      <groupId>org.xolstice.maven.plugins</groupId>
      <artifactId>protobuf-maven-plugin</artifactId>
      <version>0.6.1</version>
      <configuration>
        <protocArtifact>com.google.protobuf:protoc:3.25.1:exe:${os.detected.classifier}</protocArtifact>
        <pluginId>grpc-java</pluginId>
        <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.60.0:exe:${os.detected.classifier}</pluginArtifact>
        <protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
      </configuration>
      <executions>
        <execution>
          <goals><goal>compile</goal></goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Step 2: Place Proto and Generate

Put veilnet.proto in src/main/proto/. Ensure google/protobuf/empty.proto is available (add protoc-gen-grpc-java include path or a google/protobuf directory).

mvn compile

Step 3: Use the Generated Client

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;

// ManagedChannel channel = ManagedChannelBuilder
//     .forTarget("127.0.0.1:1993")
//     .usePlaintext()
//     .build();
// AnchorGrpc.AnchorBlockingStub stub = AnchorGrpc.newBlockingStub(channel);

// stub.startAnchor(StartAnchorRequest.newBuilder()
//     .setGuardianUrl("https://guardian.veilnet.app")
//     .setAnchorToken("your-registration-token")
//     .setIp("")
//     .setRift(false)
//     .setPortal(false)
//     .build());

// stub.addTaint(AddTaintRequest.newBuilder().setTaint("web").build());
// GetInfoResponse info = stub.getInfo(Empty.getDefaultInstance());
// System.out.println("VeilNet IP: " + info.getCidr());

// When done: stub.stopAnchor(Empty.getDefaultInstance());

Typical Workflow

  1. Get credentials – Registration token from console.veilnet.app or Guardian API.
  2. Start Anchor binary – Run the platform-specific binary; it will create the TUN interface and start the gRPC server.
  3. Connect and call StartAnchor – Pass guardian_url, anchor_token, and optional ip, rift, portal.
  4. Add taints – Use AddTaint to set labels like web, api, database for access control.
  5. Use the VeilNet IP – Call GetInfo to get cidr; bind your app to that address for incoming traffic, or use it as the source for outbound VeilNet traffic.
  6. Shutdown – Call StopAnchor via gRPC first, then terminate the subprocess. Do not kill the subprocess before calling StopAnchor.

Warning: Always call StopAnchor before killing the Anchor subprocess. This allows the Anchor to shut down gracefully and clean up network resources. Killing the subprocess without calling StopAnchor first may leave the TUN interface and network state in an inconsistent state.

Note: Taints control which nodes can communicate. Two nodes can talk only if one node's taints are a subset or superset of the other's. See Taint-based access control for details.

Reference: Anchor gRPC API

RPCRequestResponse
StartAnchorStartAnchorRequestEmpty
StartAnchorWithFDStartAnchorWithFDRequestEmpty
StopAnchorEmptyEmpty
AddTaintAddTaintRequestEmpty
RemoveTaintRemoveTaintRequestEmpty
GetInfoEmptyGetInfoResponse
GetRealmInfoEmptyGetRealmInfoResponse
GetVeilInfoEmptyGetVeilInfoResponse
GetTracerConfigEmptyTracerConfig

Resources

VeilNet • © 2026 All rights reserved