Skip to content

UltraDAGcom/core

Repository files navigation

UltraDAG

Bug Bounty Security Policy Testnet Mainnet License Rust

Minimal DAG-BFT blockchain in Rust. Sub-4 MB full-node binary, 2–3 round deterministic finality, passkey-native wallets, runs on a $15 Raspberry Pi Zero 2 W. Built for IoT and machine-to-machine micropayments. Live testnet + active bug bounty.

Ed25519 signatures · DAG-BFT consensus · BLAKE3 hashing · 21M max supply · 7-bucket emission · WebAuthn smart accounts

🔒 Security & Bug Bounty

Active Bug Bounty Program — 500,000 UDAG pool. Find a vulnerability, get paid.

Severity Reward Range
🔴 Critical 10,000 – 50,000 UDAG
🟠 High 5,000 – 10,000 UDAG
🟡 Medium 1,000 – 5,000 UDAG
🟢 Low 100 – 1,000 UDAG

All testing happens on testnet — mainnet is currently closed to external participation while the bounty program hardens the code. See PROGRAM.md for the mainnet access policy.

Reports are private via GitHub Security Advisories. Testnet resets do not affect any reward commitment — the append-only LEDGER.md is the binding record, not on-chain balances. See LEDGER.md → Testnet Reset Safety for why.

View Full Program → · Hunter's Guide → · Report a Vulnerability →

What is UltraDAG

UltraDAG is a DAG-BFT consensus protocol designed for permissioned networks and IoT applications. It uses a directed acyclic graph (DAG) structure instead of a linear blockchain, enabling parallel block production by multiple validators. The protocol achieves Byzantine fault tolerance with deterministic finality—once a vertex is finalized, it cannot be reverted. There is no proof of work.

How It Works

In UltraDAG, each validator produces one vertex per round. Each vertex references all known tips from the previous round, forming a DAG structure where multiple validators produce blocks concurrently. A vertex achieves finality when 2/3+ of validators have produced at least one descendant of it. This provides immediate, deterministic finality without waiting for confirmations.

Round duration: Design target is 30 seconds, but configurable via --round-ms flag. Testnet currently runs at 5 seconds for faster testing.

Transaction ordering is deterministic: finalized vertices are sorted by (round, topological depth, hash) before applying to state. This ensures all nodes derive identical account balances from the same set of finalized vertices.

Tokenomics

  • Max supply: 21,000,000 UDAG (hard cap enforced in state engine)
  • 7-bucket distribution: 88% per-round emission + 12% IDO genesis pre-mine
    • 44% validators/stakers (9.24M, proportional to effective stake)
    • 16% DAO treasury (3.36M, spent via Council TreasurySpend proposals)
    • 12% IDO / Liquidity (2.52M, genesis pre-mine to IDO distributor multisig — private round + Uniswap seed)
    • 10% Council of 21 (2.1M, equal split among seated members)
    • 8% ecosystem (1.68M, multisig for airdrops/grants)
    • 5% founder (1.05M, earned through emission, starts at 0)
    • 5% reserve (1.05M, strategic multisig)
  • Halving: every 10,500,000 rounds (~1.66 years at 5s rounds)
  • Initial nominal block reward: 1 UDAG per round. The six emission buckets take 88% of this; the remaining 12% is never minted and offsets the IDO pre-mine so the 21M cap holds exactly.
  • Faucet reserve: 1,000,000 UDAG at genesis (testnet only, excluded from mainnet)
  • Validator rewards: Proportional to stake when staking is active
    • Pre-staking fallback: validator pool (44% of block reward) split equally among configured validators
    • Post-staking: validator pool split proportionally by effective stake + delegations
  • Minimum stake: 2,000 UDAG
  • Unstaking cooldown: 2,016 rounds (~2.8 hours at 5s rounds)
  • Slashing: 50% stake burn on equivocation (governable 10-100%)

Running a Node

Docker (Recommended)

Easiest way to run on Linux, macOS, or Windows:

# Single node
docker run -p 9333:9333 -p 10333:10333 \
  ghcr.io/ultradagcom/core:latest --port 9333 --validate

# 4-node local network
docker-compose up -d

Full Docker Guide →

Running a Validator

The fastest way to get a validator running on testnet:

# Step 1: Generate a keypair
curl https://ultradag-node-1.fly.dev/keygen

# Step 2: Get testnet UDAG (100,000 UDAG for staking)
curl -X POST https://ultradag-node-1.fly.dev/faucet \
  -H "Content-Type: application/json" \
  -d '{"address":"<your-address>","amount":10000000000000}'

# Step 3: Run your validator node (auto-stakes 10,000 UDAG on startup)
cargo run --release -p ultradag-node -- \
  --port 9333 --validate \
  --pkey <your-secret-key> \
  --auto-stake 10000

The --pkey flag lets you bring your own Ed25519 private key (64-char hex) instead of auto-generating one. The --auto-stake flag automatically submits a stake transaction after the node syncs with the network.

From Source

# Run a validator node (RPC on port 10333)
cargo run --release -p ultradag-node -- --port 9333 --validate

# Bring your own key
cargo run --release -p ultradag-node -- --port 9333 --validate --pkey <hex-secret-key>

# Connect a second validator
cargo run --release -p ultradag-node -- --port 9334 --seed 127.0.0.1:9333 --validate

# Custom round duration (default 5000ms)
cargo run --release -p ultradag-node -- --port 9335 --seed 127.0.0.1:9333 --validate --round-ms 3000

# Fixed validator count (prevents phantom inflation)
cargo run --release -p ultradag-node -- --port 9333 --validate --validators 4

API Reference

HTTP RPC runs on P2P port + 1000 (e.g., P2P 9333 → RPC 10333).

Core Endpoints

GET /status — Node status

{
  "last_finalized_round": 1863,
  "dag_round": 1865,
  "total_supply": 109505000000000,
  "total_staked": 4000000000000,
  "active_stakers": 4,
  "peers": 13,
  "mempool_size": 0
}

GET /balance/:address — Account balance and nonce

{
  "balance_sats": 5000000000,
  "balance_udag": 50.0,
  "nonce": 0
}

POST /tx — Submit transaction

{
  "from_secret": "<64-char-hex>",
  "to": "<64-char-hex>",
  "amount": 1000000000,
  "fee": 100000
}

GET /keygen — Generate new keypair

{
  "secret_key": "<64-char-hex>",
  "address": "<64-char-hex>"
}

POST /faucet — Testnet faucet (testnet only)

{
  "address": "<64-char-hex>",
  "amount": 1000000000
}

Staking Endpoints

POST /stake — Lock UDAG as validator stake

  • Minimum stake: 10,000 UDAG (1,000,000,000,000 sats)
  • Request:
{
  "secret_key": "<64-char-hex>",
  "amount": 1000000000000
}
  • Response: Transaction hash and confirmation
  • Note: Stake becomes active at the next epoch boundary (every 210,000 rounds)

POST /unstake — Begin unstake cooldown (~2.8 hours at 5s rounds)

  • Cooldown: 2,016 rounds before funds are returned (~2.8 hours at 5s rounds)
  • Request:
{
  "secret_key": "<64-char-hex>"
}
  • Response: Transaction hash and unlock round
  • Note: Validator is removed from active set immediately; funds return after cooldown

GET /stake/:address — Query stake status for an address

  • Response:
{
  "staked": 1000000000000,
  "unlock_at_round": null,
  "is_active_validator": true
}
  • Fields:
    • staked: Current staked amount in sats
    • unlock_at_round: Round when unstaked funds will be available (null if not unstaking)
    • is_active_validator: Whether address is in the active validator set

GET /validators — List all active validators and their stakes

  • Response:
[
  {
    "address": "a1b2c3...",
    "stake": 1000000000000
  }
]
  • Note: Validators are sorted by stake amount (descending). Max 21 active validators.

DAG Endpoints

GET /round/:round — Vertices in a specific round GET /mempool — Pending transactions (top 100 by fee) GET /peers — Connected peers

Test Suite

cargo test --workspace --release

757 tests passing (all pass, 14 ignored jepsen long-running tests)

  • ultradag-coin: 146 unit + 399 integration tests
  • ultradag-network: 25 unit + 12 integration tests + 49 fault injection tests
  • ultradag-sdk: 2 doc tests

Test coverage includes: consensus safety, Byzantine fault tolerance, cryptographic correctness, double-spend prevention, staking lifecycle, supply invariants, state persistence, crash recovery, checkpoint production, fast-sync, equivocation evidence retention.

Architecture

3 crates, strict layering:

Crate Purpose
ultradag-coin Ed25519 keys, DAG-BFT consensus, StateEngine, staking, account-based state
ultradag-network TCP P2P: peer discovery, DAG vertex relay, state synchronization
ultradag-node Full node binary: validator + networking + HTTP RPC

Formal Verification

The consensus protocol has a TLA+ formal specification verified by the TLC model checker. Six invariants were checked exhaustively across 32.6 million states with zero violations:

  • Safety — No conflicting finalized vertices from the same validator in the same round
  • HonestNoEquivocation — Honest validators never equivocate
  • FinalizedParentsConsistency — All parents of finalized vertices are also finalized
  • TypeOK, RoundMonotonicity, ByzantineBound — Structural invariants

Verified at N=4 validators, 1 Byzantine, 2 rounds. See formal/VERIFICATION.md for full results and limitations.

Known Limitations

  • Pre-staking emission: Total emission scales with validator count until first validator stakes. After staking activates, emission is fixed per round.
  • No per-peer rate limiting: Acceptable for current permissioned validator set.
  • Round synchronization: Nodes produce at independent round numbers, preventing in-round quorum. Finality happens via descendant accumulation across rounds.
  • Vertex ordering: O(V²) for the ordering step (not finality). Acceptable for <=21 validators.

Cryptography

  • Signing: Ed25519 via ed25519-dalek
  • Addresses: blake3(ed25519_public_key) — 32 bytes
  • Transactions: carry sender's public key for on-chain verification
  • DAG vertices: Ed25519-signed by the proposing validator
  • Block hashing: Blake3
  • Replay protection: NETWORK_ID prefix on all signable bytes

License

Business Source License 1.1 (BISL) - see LICENSE file.

Summary:

  • Free to use for operating validators, building wallets/explorers, and developing applications on UltraDAG
  • Cannot be used to launch competing blockchain networks
  • Converts to MIT License on March 10, 2030

About

Minimal DAG-BFT blockchain in Rust. Sub-4 MB full-node binary, 2–3 round deterministic finality, passkey-native wallets, runs on a $15 Raspberry Pi Zero 2 W. Built for IoT and machine-to-machine micropayments. Live testnet + 500k UDAG bug bounty.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages