Skip to content

Repository files navigation

Rinku: A DAG-Based Distributed Ledger For Mesh-Native Systems

Rust CI Node.js CI Coverage (Rust) Network Health Protocol Checkpoints Finality

Testnet nodes: Genesis Validator-1 Validator-2


A DAG-based distributed ledger with tunable consistency, designed for mesh-native and partition-prone environments. Delivers CP-like checkpoint finality during normal operation, provisional availability during partitions, and deterministic merge reconciliation when connectivity is restored. Self-contained VerifiableObject proofs enable offline verification without RPC infrastructure.

whitepaper

Quick Start

Prerequisites

  • Rust (1.75+) - Install via rustup
  • Node.js (18+) - For the explorer

Build the Node

# Clone and build
git clone <repo-url>
cd rinku

# Build the Rust node
cargo build -p rinku-node --release

Run Locally (Standalone Genesis Node)

# Start a fresh local node
RUST_LOG=info cargo run -p rinku-node

# Or run in TUI mode (terminal interface)
RUST_LOG=info cargo run -p rinku-node --features tui -- --tui

Connecting to Testnet via TUI

To sync your local node with the live Fly.io testnet validators:

Step 1: Get Bootstrap Info from Testnet

# Get the P2P bootstrap info from the genesis node
curl https://rinku-genesis.fly.dev/api/bootstrap

This returns the peer ID and multiaddr needed to connect via P2P.

Step 2: Run Local Node with Testnet Peers

From the bootstrap response, extract these values:

  • peerId — the genesis node's libp2p peer ID
  • genesisValidatorEnv — the address:blsPublicKey string for GENESIS_VALIDATORS

Then look up the genesis node's public IPv4 (shown in the bootstrap response's bootstrapMultiaddr field, or via fly ips list -a rinku-genesis).

# Required: P2P connection to the testnet
export P2P_BOOTSTRAP_PEERS="/ip4/<GENESIS_IP>/tcp/4001/p2p/<PEER_ID>"

# Required: Trust anchor — tells your node which validators are authorized
# Use the genesisValidatorEnv value from /api/bootstrap
# For multiple validators, separate with semicolons: "addr1:bls1;addr2:bls2;addr3:bls3"
export GENESIS_VALIDATORS="<ADDRESS>:<BLS_PUBLIC_KEY>"

# Required: Must match the testnet's chain/network identity
export CHAIN_ID="rinku-testnet"
export NETWORK_ID="testnet"

# Required: Mainnet mode enforces strict validation (the testnet runs with this enabled)
export MAINNET_MODE="true"

# Required: Your node's reachable URL (used for leader election protocol)
export PUBLIC_URL="http://localhost:3001"

# Optional: HTTP peer for fallback sync (in addition to P2P)
export NODE_PEERS="https://rinku-genesis.fly.dev"

# Logging
export RUST_LOG="rinku_node=info"

# Run in TUI mode
cargo run -p rinku-node --features tui -- --tui

Or as a single command:

P2P_BOOTSTRAP_PEERS="/ip4/<GENESIS_IP>/tcp/4001/p2p/<PEER_ID>" \
GENESIS_VALIDATORS="<ADDRESS>:<BLS_PUBLIC_KEY>" \
CHAIN_ID="rinku-testnet" \
NETWORK_ID="testnet" \
MAINNET_MODE="true" \
PUBLIC_URL="http://localhost:3001" \
NODE_PEERS="https://rinku-genesis.fly.dev" \
RUST_LOG="rinku_node=info" \
cargo run -p rinku-node --features tui -- --tui

Important notes:

  • Use /ip4/ (not /dns4/) when the bootstrap address is a raw IP
  • CHAIN_ID and NETWORK_ID must match the testnet — mismatches cause handshake rejection
  • Without GENESIS_VALIDATORS, your node cannot verify checkpoint signatures during sync
  • IS_GENESIS_NODE is auto-detected as false when P2P_BOOTSTRAP_PEERS is set

Step 3: Verify Sync

In the TUI, you should see:

  • Checkpoint height increasing as you sync
  • DAG size growing
  • Peer count > 0 once connected

Or via API:

curl http://localhost:3001/api/sync/status
curl http://localhost:3001/api/dag/summary

Testnet Nodes

Node URL Purpose
Genesis https://rinku-genesis.fly.dev Primary testnet node
Validator 1 https://rinku-validator-1.fly.dev Validator node
Validator 2 https://rinku-validator-2.fly.dev Validator node

Environment Variables

Core Configuration

Variable Description Default
API_PORT HTTP API port 3001
DATA_DIR Database storage path .rinku-data
CHAIN_ID Chain identifier (must match network) rinku-mainnet
NETWORK_ID Network identifier mainnet
RUST_LOG Log level (debug, info, warn, error) info
IS_GENESIS_NODE Allow creating new chain if no peers auto-detected

P2P Networking

Variable Description Default
P2P_ENABLED Enable libp2p networking true
P2P_PORT P2P listen port 4001
P2P_BOOTSTRAP_PEERS Comma-separated multiaddrs ""
P2P_MDNS Enable mDNS for LAN discovery true
P2P_MAX_PEERS Maximum peer connections 50

HTTP Sync

Variable Description Default
NODE_PEERS Comma-separated HTTP peer URLs ""

Validator Mode

Variable Description Default
MAINNET_MODE Enforce mainnet-grade security false
PUBLIC_URL Node's public URL for leader election ""
GENESIS_VALIDATORS Genesis validator set (addr:bls;...) ""
RATE_LIMIT_TX_MAX Max tx submits per IP per minute 30
RATE_LIMIT_CONTRACT_MAX Max contract deploy/call per IP per minute 20
RATE_LIMIT_GENERAL_MAX Max general write ops (e.g. faucet) per IP per minute 100
FAUCET_ENABLED Enable faucet mint endpoints true unless MAINNET_MODE
CORS_ALLOW_ORIGINS Comma-separated origins for write-route CORS (* = any) localhost explorer ports

Wallet Key Management

The node generates an ECDSA P-256 wallet on first startup, stored encrypted at <DATA_DIR>/validator.key. This wallet holds RKU, stakes, and receives staking rewards.

Export Your Node's Wallet Key

# Show the wallet address only
cargo run -p rinku-node -- --show-address

# Export wallet JSON (compatible with Explorer import)
VALIDATOR_KEY_PASSWORD="your-password" cargo run -p rinku-node -- --export-key

The wallet JSON is printed to stdout (instructions go to stderr), so you can pipe it:

VALIDATOR_KEY_PASSWORD="your-password" cargo run -p rinku-node -- --export-key > my-wallet.json

The exported JSON contains publicKey, privateKey (PKCS8 DER hex), and fingerprint — the same format used by the Explorer wallet.

Import a Wallet Key Into a Node

# Import from wallet JSON (exported from Explorer or another node)
VALIDATOR_KEY_PASSWORD="your-password" cargo run -p rinku-node -- --import-key '{"publicKey":"04...","privateKey":"3081...","fingerprint":"..."}'

# Import from PKCS8 DER hex
VALIDATOR_KEY_PASSWORD="your-password" cargo run -p rinku-node -- --import-key 308187020100...

# Import from raw 32-byte private key hex
VALIDATOR_KEY_PASSWORD="your-password" cargo run -p rinku-node -- --import-key 368e9a5471...

This lets you use the same wallet identity across the Explorer and your validator node. The key is encrypted with your VALIDATOR_KEY_PASSWORD before being saved.

Note: In MAINNET_MODE, VALIDATOR_KEY_PASSWORD must be explicitly set (the default dev-password is rejected).

Key File Location

File Contents
<DATA_DIR>/validator.key Encrypted ECDSA private key (wallet for RKU transactions)
<DATA_DIR>/validator-identity/validator_keys.json BLS signing keys (for checkpoint signatures)

TUI Mode

The TUI (Terminal User Interface) provides a real-time dashboard for monitoring node state:

# Build with TUI feature
cargo build -p rinku-node --features tui

# Run TUI
cargo run -p rinku-node --features tui -- --tui

TUI displays:

  • Checkpoint height and DAG size
  • Connected peers
  • Transaction throughput
  • Finality metrics
  • Network status

Explorer

The web-based block explorer runs on port 5000:

# Build core library and start explorer
npm run build -w @rinku/core
npm run dev -w @rinku/explorer

Visit http://localhost:5000 to view:

  • DAG visualization
  • Account balances
  • Transaction history
  • Staking interface
  • Faucet

API Endpoints

The node exposes a REST API on port 3001:

Endpoint Description
GET /api/dag/summary DAG statistics
GET /api/accounts All accounts
GET /api/account/:addr Account details
GET /api/tx/:hash Transaction details
POST /api/tx Submit transaction
GET /api/sync/status Sync status
GET /api/bootstrap P2P bootstrap info
GET /api/peers Connected peers
GET /api/finality/metrics Finality statistics

Project Structure

rinku/
├── packages/
│   ├── rinku-core/           # Protocol primitives: crypto, merkle, checkpoints (Rust)
│   ├── rinku-node/           # Full node: consensus, P2P, API server (Rust)
│   ├── rinku-contract-sdk/   # WASM smart contract SDK (Rust)
│   ├── core/                 # Protocol primitives (TypeScript dual of rinku-core)
│   ├── wallet/               # Wallet helpers for Explorer and clients
│   ├── zk/                   # Zero-knowledge privacy layer (Circom + TS)
│   ├── explorer/             # React block explorer (includes faucet UI)
│   ├── stateless/            # Stateless dApp helpers (ContractOutput proofs)
│   └── examples/             # Sample WASM contracts
├── scripts/                  # Deployment, validation, and stress-test harnesses
├── docs/                     # Versioning, architecture notes, whitepaper
├── fly.toml                  # Fly.io node deployment config
├── Cargo.toml                # Rust workspace
└── package.json              # npm workspaces

Development

Run All Services Locally

# Terminal 1: Rust node
RUST_LOG=info cargo run -p rinku-node

# Terminal 2: Explorer (port 5000; faucet UI talks to the node API)
npm run build -w @rinku/core && npm run dev -w @rinku/explorer

Run Tests

# Rust tests
cargo test

# TypeScript tests
npm test

Documentation


License

MIT

About

A dag-based distributed ledger for mesh-native systems

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages