RillCoin
RillCoin DocsTestnet Live
Protocol

Protocol Architecture

Crate graph, data structures, UTXO model, block format, and network layer design.

Crate Graph

RillCoin is implemented as a Cargo workspace with six library crates and three binary crates. Dependencies flow strictly from lower to higher layers — no circular dependencies.

rill-core
Types, constants, errors, crypto primitives
rill-decay
Sigmoid table, decay rate, cluster tracking
rill-consensus
Block validation, PoW, difficulty adjustment
rill-network
libp2p transport, Gossipsub, Kademlia DHT
rill-wallet
HD wallet, coin selection, signing
rill-node
RPC server, storage, mempool, sync
rill-core
Foundation layer

Defines all shared types (Transaction, Block, BlockHeader, UTXO, Address, TxInput, TxOutput), protocol constants, error types, and cryptographic primitives. All other crates depend on rill-core. No external blockchain dependencies.

rill-decay
Decay engine

Implements the sigmoid lookup table, fixed-point decay rate calculation, cluster balance aggregation, lineage tracking, and the decay pool state machine. Exposes pure functions — no I/O, no side effects.

rill-consensus
Consensus rules

Block and transaction validation logic, proof-of-work verification, difficulty adjustment algorithm, Merkle root computation, coinbase maturity checks, and fee validation. The single source of truth for what constitutes a valid block.

rill-network
P2P networking

libp2p-based networking: TCP transport, Noise handshake, Gossipsub block/tx propagation, Kademlia peer discovery, and connection management. Handles peer scoring and ban lists.

rill-wallet
Wallet logic

HD wallet derivation (BIP-32-style with Ed25519), address generation, decay-aware coin selection (spends highest-decay UTXOs first), transaction construction, and signing.

rill-node
Node binary

Integrates all library crates. Hosts the JSON-RPC 2.0 server, manages RocksDB storage, drives the mempool, coordinates block sync, and runs the decay application engine.

Transaction Structure

Transactions use a standard UTXO model. Each transaction consumes one or more UTXOs (inputs) and creates one or more new UTXOs (outputs).

Transaction (rill-core/src/types.rs)
pub struct Transaction {
    pub version:   u64,
    pub inputs:    Vec<TxInput>,
    pub outputs:   Vec<TxOutput>,
    pub lock_time: u64,
}

pub struct TxInput {
    pub prev_txid:    [u8; 32],   // BLAKE3 hash of previous transaction
    pub prev_index:   u32,        // Index of the output being spent
    pub signature:    [u8; 64],   // Ed25519 signature
    pub pubkey:       [u8; 32],   // Ed25519 public key
}

pub struct TxOutput {
    pub value:        u64,        // Amount in rills (1 RILL = 100_000_000)
    pub pubkey_hash:  [u8; 20],   // BLAKE3(pubkey)[..20] — address payload
    pub cluster_id:   [u8; 32],   // BLAKE3 cluster identifier
}

Transaction ID

A transaction ID (txid) is computed as BLAKE3(bincode::serialize(transaction)) — the BLAKE3 hash of the bincode-serialized transaction bytes. This is a 32-byte value, displayed as lowercase hex.

Signing

Each input is signed independently. The signing message is the serialized transaction with all input signatures zeroed out, committed to with the signer's Ed25519 key. The signature and public key are embedded in the input itself.

UTXO Model & Cluster Tracking

RillCoin extends the standard UTXO model with cluster tracking. Every UTXO carries a cluster_id — a 32-byte BLAKE3 hash that groups economically related UTXOs for decay calculation. All UTXOs sharing a cluster_id are aggregated when computing concentration.

The cluster_id is set at UTXO creation time. Wallet implementations should assign the same cluster_id to all outputs controlled by the same economic actor, or use the default derivation:

formula
default_cluster_id = BLAKE3(wallet_root_pubkey)

This prevents decay evasion through address splitting: even if a holder distributes coins across thousands of addresses, as long as they share a cluster_id, the full aggregate is subject to decay.

Block Structure

Block (rill-core/src/types.rs)
pub struct Block {
    pub header:       BlockHeader,
    pub transactions: Vec<Transaction>,
}

pub struct BlockHeader {
    pub version:           u32,
    pub prev_hash:         [u8; 32],   // SHA-256 hash of previous header
    pub merkle_root:       [u8; 32],   // BLAKE3 Merkle root of transactions
    pub timestamp:         u64,        // Unix seconds
    pub difficulty_target: u32,        // Compact nBits format
    pub nonce:             u64,        // Proof-of-work nonce
}

Block Hash

The block hash is computed as SHA-256(SHA-256(bincode(block_header))). A block is valid if its hash, interpreted as a 256-bit big-endian integer, is less than the target derived from difficulty_target.

Coinbase Transaction

The first transaction in every block must be a coinbase transaction. Coinbase transactions have no inputs (or a single input with a null prevout). The output value must equal the block subsidy plus transaction fees plus the decay pool release for that block. Coinbase outputs cannot be spent until the UTXO has been buried by COINBASE_MATURITY = 100 additional blocks.

Address Encoding

RillCoin addresses use Bech32m encoding (BIP-350). The address payload is a 20-byte prefix of the BLAKE3 hash of the Ed25519 public key.

formula
address_payload = BLAKE3(ed25519_pubkey_bytes)[0..20]
address_string  = bech32m_encode(hrp, address_payload)

where hrp:
  mainnet → "rill1"
  testnet → "trill1"

Example addresses

testnettrill1qw5r3k8d9...
mainnetrill1qw5r3k8d9...

Network Magic Bytes

Each network is identified by a 4-byte magic value prepended to all P2P messages. This prevents cross-network contamination.

NetworkMagic (ASCII)Magic (hex)P2P PortRPC Port
MainnetRILL0x52494C4C1833318332
TestnetTEST0x544553542833328332
RegtestREGT0x524547543833338332