pluriƀit

Digital cash, native to the web.

Get pluriƀit

Core Principles

pluriƀit is an experimental digital cash protocol built on three core principles.

Private by Default

All transactions are confidential. Using Mimblewimble, all amounts and addresses are obscured on-chain. Privacy is a mandatory feature of the protocol, not an optional one.

Fair & Decentralized Consensus

A novel Proof-of-Time consensus mechanism eliminates the hardware arms race of Proof-of-Work and the "rich-get-richer" capital accumulation of Proof-of-Stake. Block production is open to anyone, with fairness enforced by verifiable, time-based cryptography.

Web-Native & Peer-to-Peer

The network is truly peer-to-peer, with no centralized servers or trusted endpoints. Built on libp2p and Wasm, it natively supports WebRTC, WebSockets, and TCP, allowing nodes to run in any modern environment, including directly in the browser.

How Consensus Works: A Proof-of-Time Lottery

pluriƀit replaces the energy-intensive "hash grinding" of Proof-of-Work with a fair, time-based process. This is a three-stage lottery that anyone can play.

graph TD A[Start: New Nonce] --> B["Compute VDF: y = x^(2^t) mod N"] B --> C[Compute VRF with y] C --> D{vrfOutputHex < thresholdHex?} D -- Yes --> E[Produce Block] D -- No --> A style A fill:#f9f,stroke:#333 style E fill:#cfc,stroke:#333
1. The "Work": A Verifiable Delay Function (VDF)

How it works

Instead of a parallel search for a hash, producers perform a *sequential* search. For each new nonce (e.g., 0, 1, 2...), they must compute a Verifiable Delay Function (VDF). This function, y = x^(2^t) mod N, takes a fixed amount of real time to compute and cannot be significantly parallelized.

  • No Arms Race: This neutralizes the advantage of specialized hardware (ASICs/FPGAs). A 1000-core machine is no faster at this task than a single-core machine.
  • Binding: The VDF input is a unique string binding the block height, previous hash, miner's key, and the nonce. This ensures each attempt is unique to a specific miner and block.
2. The "Lottery": A Verifiable Random Function (VRF)

How it works

The unique output of the VDF (the y value) is then used as the input for a Verifiable Random Function (VRF). The VRF acts as a lottery, producing a fair, unpredictable, and verifiable random number using the producer's secret key.

  • Provably Fair: The two-step (VDF -> VRF) process proves the miner *had* to wait for the VDF to finish before they could know if they won. They cannot "grind" for a winning VRF output by trying millions of inputs per second.
  • Winning: If the VRF's random number is below the network's current difficulty threshold (e.g., vrfOutputHex < thresholdHex), the miner wins the right to produce the block.
3. The "Fork-Choice": GHOST Rule

How it works

To resolve network forks, pluriƀit uses the GHOST (Greedy Heaviest Observed Subtree) rule. When two competing chains exist, nodes don't simply pick the "longest" one.

  • Heaviest Subtree: Nodes select the chain with the most accumulated *work* (total VDF+VRF difficulty) in its *entire* subtree, including all known descendant blocks (even those on small forks).
  • Security: This method ensures the network always converges on the chain with the most total computational effort behind it, providing strong security against selfish mining and other attacks.
graph TD Genesis --> Chain1[Chain 1
Work: 10] Genesis --> Chain2[Chain 2
Work: 5] Chain1 --> Sub1[Sub 1
Work: 8] Chain1 --> Sub2[Sub 2
Work: 7] Chain2 --> Sub3[Sub 3
Work: 6] subgraph "Heaviest Subtree (Chain 1: 10+8+7=25)" Chain1 Sub1 Sub2 end style Chain1 fill:#cfc,stroke:#333

How Privacy Works

Privacy is mandatory and enforced at multiple layers of the protocol.

Confidential Transactions (Mimblewimble)

Hiding Amounts with Pedersen Commitments

All transaction amounts are hidden using Pedersen Commitments. Instead of recording value = 100, the chain records a commitment C = 100*H + b*G, where b is a secret "blinding factor".

  • An observer can't see the value 100.
  • The network can still verify the math. A balanced transaction (Inputs = Outputs + Fee) holds true in the elliptic curve world: Sum(Input_C) = Sum(Output_C) + Kernel_Excess.

Proving Positivity with Aggregated Bulletproofs

Commitments alone aren't enough; a sender could create a -100 output to steal funds. To prevent this, all outputs must be proven to be positive numbers. pluriƀit uses Aggregated Bulletproofs, a single, highly efficient proof that covers *all* outputs in a transaction, saving significant block space.

Private Payments (Stealth Addresses)

How it Works (Sender)

To pay Bob, Alice only needs his public stealth address (e.g., pb1...).

  1. Alice generates a new, one-time secret r and computes a public ephemeral key R = r*G.
  2. She uses Bob's public scan key (Ps) to compute a shared secret: s = Hs(r * Ps).
  3. Alice uses this secret s to encrypt the value and blinding factor of the transaction.
  4. She broadcasts the transaction, which includes R and the encrypted data.

How it Works (Receiver)

Bob's wallet scans the blockchain for transactions. For each one:

  1. It uses its private scan key (ps) and the transaction's ephemeral key (R) to compute the same shared secret: s' = Hs(ps * R).
  2. It uses this secret to try and decrypt the transaction data.
  3. If decryption is successful, the wallet has found its funds. It adds the value and blinding factor to its UTXO set and can now spend it using its private spend key.

This process is non-interactive (Bob doesn't need to be online) and breaks all on-chain links between payments to the same recipient.

Optimization: View Tags

The calculation ps * R is computationally expensive. To speed this up, the sender also derives a 1-byte View Tag from the shared secret (tag = Hs("view_tag" || s)). The wallet first checks this tag. If it doesn't match, it can skip the expensive decryption, discarding ~99.6% of all outputs almost instantly.

sequenceDiagram participant Alice participant Blockchain participant Bob Alice->>Alice: Generate r, R = r*G Alice->>Alice: s = Hs(r * Ps_Bob) Alice->>Alice: Encrypt value & blinding with s Alice->>Blockchain: Broadcast Tx (R, encrypted data) Bob->>Blockchain: Scan Tx Bob->>Bob: s' = Hs(ps * R) Bob->>Bob: Decrypt if s' matches, add to UTXO
Anonymous Broadcasting (Dandelion)

To hide a transaction's origin IP, nodes use Dandelion propagation.

  • Stem Phase: When a node creates a transaction, it doesn't broadcast it. Instead, it sends it to *one* randomly chosen peer. This peer has a 90% chance (STEM_PROBABILITY) to pass it to *one* other peer, and so on. This is the "stem" phase.
  • Fluff Phase: Eventually, a node will, by 10% chance, "fluff" the transaction, broadcasting it to all its peers. This breaks the link between the transaction and its origin, making IP-based surveillance difficult.
graph LR A[Originator] -- Stem --> B[Peer 1] B -- Stem 90% --> C[Peer 2] B -- Fluff 10% --> D[Broadcast] C -- Stem 90% --> E[Peer 3] C -- Fluff 10% --> F[Broadcast] style A fill:#f66,stroke:#333 style D fill:#cfc,stroke:#333 style F fill:#cfc,stroke:#333
A Lighter Chain (Block-level Cut-through)

To keep the blockchain small and efficient, pluriƀit performs "cut-through" at the block level. This is a process of removing redundant, internal transaction data before the block is finalized.

  1. First, the coinbase transaction (the miner's reward) is isolated.
  2. The node finds all "internal spends" — outputs that are created and spent *within the same block*.
  3. These internal inputs and outputs (which cancel each other out) are removed.
  4. All remaining (non-coinbase) transactions are combined into a single aggregated transaction for that block. This transaction contains only the external inputs and the final, unspent outputs.
  5. All transaction kernels are then concatenated into this single aggregated transaction.

Design Choice: Concatenation vs. Aggregation

This is a key difference from other Mimblewimble protocols like Grin, which aggregate kernels. Aggregating kernels (cryptographically combining them into one) requires an interactive process where all transaction participants must cooperate to build the final, combined kernel.

pluriƀit concatenates kernels (simply listing them one after another) to specifically remove this need for interactivity. This design is what enables non-interactive Stealth Address payments, allowing a sender to create and broadcast a transaction at any time without the receiver needing to be online. This approach maintains the cryptographic balance (Sum(Inputs) = Sum(Outputs) + Kernels), full supply auditability and non-interactive payments.

graph TD A[Block with Txns] --> B[Isolate Coinbase] A --> C[Find Internal Spends] C --> D[Remove Internal I/O] D --> E[Aggregate Remaining Txns] E --> F[Concatenate Kernels] F --> G[Final Block] style A fill:#f9f,stroke:#333 style G fill:#cfc,stroke:#333

Game Theory & Economics

The protocol's monetary policy and consensus stability are governed by two key mechanisms that work in tandem.

Coin Issuance & Supply Schedule

How New Coins are Created

New coins are created in the first transaction of every block, known as the Coinbase Transaction. This transaction has no inputs and creates new value, which is assigned to the block producer as their reward.

The smallest unit of account is a "bit". 1 pluriƀit (ƀ) = 100,000,000 bits.

The Block Reward

The number of new bits created in each block follows a fixed, predictable schedule:

  • Initial Reward: The starting reward is 50,000,000 bits (0.5 ƀ) per block.
  • Halving: This reward is cut in half every 525,600 blocks (approximately every 6 months).
  • Reward Era: This halving cycle continues for approximately 5 years (5,256,000 blocks). After this "Reward Era" is complete, the entire schedule resets, starting a new era with the initial reward.

Auditable Supply

This deterministic schedule makes the total supply fully predictable and auditable. The total supply at any given time is simply the sum of all base block rewards from block 1 to the current height.

Transaction fees are not new coins. They are existing bits transferred from the user to the block producer. The coinbase transaction's output is therefore Total Reward = Base Reward + Total Fees, but only the Base Reward portion represents new issuance.

Visualization: Block Reward and Cumulative Supply

How Difficulty is Adjusted

Why Adjust Difficulty?

The network needs to maintain a stable average block time (Target: 30 seconds). If new producers join the network, blocks will be found faster. If producers leave, blocks will be found slower. The difficulty adjustment mechanism automatically corrects for this.

In pluriƀit, this adjustment happens every 12 blocks (the DIFFICULTY_ADJUSTMENT_INTERVAL). The network uses a two-pronged approach:

1. Adjusting the "Work": VDF Iterations

This part adjusts the *time and effort* required for each lottery attempt.

  • The network measures the actual time it took to produce the last 12 blocks (actual_timespan = end_block.timestamp - start_block.timestamp).
  • It compares this to the target time (target_timespan = 12 * 30 seconds).
  • If blocks were too fast (actual_timespan < target_timespan), the vdf_iterations are increased. This makes the VDF computation take longer, slowing down block production.
  • If blocks were too slow, the vdf_iterations are decreased.
  • This adjustment is clamped (e.g., to a maximum 4x change) to prevent extreme swings from timestamp manipulation.

2. Adjusting the "Odds": VRF Threshold

This part adjusts the *probability* of winning the lottery with any given attempt.

  • If blocks were too fast, the vrf_threshold is lowered. This is like making the winning lottery numbers rarer, making it harder to win.
  • If blocks were too slow, the vrf_threshold is raised, making it easier to win.

By adjusting both the time per attempt (VDF) and the odds of winning (VRF), the network dynamically and robustly targets a stable 30-second block time.

Visualization: Hypothetical Difficulty Adjustment

A Modern, Hybrid Architecture

Secure Core: Rust + Wasm

pluriƀit uses a hybrid design for security and performance. The core cryptography, consensus rules, and state logic are written in Rust. This core is compiled to WebAssembly (Wasm), creating a secure, high-performance, and verifiable execution environment that can run anywhere.

Rust/Wasm Manages:

  • All cryptography (Mimblewimble, VDF, VRF, Stealth)
  • Consensus Rules (block & transaction validation)
  • State Logic (UTXO set, reorgs, supply audit)
  • Wallet key management and transaction creation
graph TD Rust[Rust Core] -->|Compile| Wasm[Wasm Module] Wasm --> Crypto[Cryptography] Wasm --> Consensus[Consensus Rules] Wasm --> State[State Logic] Wasm --> Wallet[Wallet Management]
Orchestration Layer: Node.js

This Wasm module is orchestrated by a Node.js runtime. The Node.js layer is responsible for all I/O and external communication, acting as the "host" for the secure Wasm core.

Node.js Manages:

  • The libp2p network stack (connecting, gossiping, discovering peers)
  • All database interactions (LevelDB)
  • Coordinating the mining worker threads
  • The JSON API server and Command-Line Interface (CLI)
graph TD NodeJS[Node.js Runtime] -->|Hosts| Wasm[Wasm Core] NodeJS --> Network[libp2p Network] NodeJS --> DB["Database (LevelDB)"] NodeJS --> Mining[Mining Workers] NodeJS --> API[JSON API & CLI]
Networking: Pure libp2p

Nodes connect directly to each other over libp2p, using gossipsub for message propagation and the Kademlia DHT for peer discovery. With full support for NAT traversal and transports like WebRTC, TCP, and WebSockets, the network is robust and censorship-resistant.

graph LR Node1 -->|WebRTC| Node2 Node1 -->|TCP| Node3 Node2 -->|WebSockets| Node3 Node3 -->|Gossipsub| Node1 subgraph "Kademlia DHT" Node1 Node2 Node3 end
Secure & Deterministic: Protobuf

All peer-to-peer messages and database entries use Protocol Buffers (Protobuf). This is a secure, efficient, and unambiguous binary format that provides a strict contract for all communication. This eliminates a wide range of text-based parsing vulnerabilities (like JSON Prototype Pollution) and ensures all nodes, regardless of platform, reach identical consensus.

Ecosystem & Tools

Command-Line Interface (CLI)

The node runs with a full command-line interface (CLI). You can create and restore wallets from a 12-word mnemonic phrase, load them into an active session, check your balance, start and stop the miner, and send private transactions.

Built-in Block Explorer & Live API

pluriƀit comes with a secure, full-featured block explorer right out of the box. It runs as a separate, lightweight web server (on port 3000 by default) that provides a clean user interface for monitoring the network in real-time.

Explorer Features:

  • Live Dashboard: View network stats like block height, total work, and UTXO count as they happen.
  • Block Train: See new blocks roll in with a live-updating "block train" visual.
  • Difficulty Charts: Visualize the network's VDF iterations and VRF threshold adjustments over time.
  • Mempool Viewer: Inspect pending transactions, fees, and network congestion.
  • Deep Search: Find any block by its height or hash, or look up a transaction by its hash to see where it was included.

Powered by the JSON API

The explorer uses the node's robust JSON API (running on port 3001), which is also available for any other developer to build ecosystem tools, wallets, or monitoring services. Available endpoints include:

  • /api/stats: Get current height, total work, and tip hash.
  • /api/mempool: See pending transactions and total fees.
  • /api/block/[height]: Get full block data for a specific height.
  • /api/block/hash/[hash]: Find a block by its hash.
  • /api/tx/[tx_hash]: Find which block a transaction was included in.
  • /api/blocks/recent: Get a summary of the most recent blocks.
  • /api/metrics/difficulty: Get historical data for difficulty charts.

Disclaimer

This is an experimental project built to explore new concepts in cryptocurrency design. It is not intended for production use and should not be used to store value. The code is provided as-is for educational and research purposes.