Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Rustchain | Rust Blockchain

A didactic blockchain written in Rust, ported from an original TypeScript implementation. The goal is learning Rust — ownership, Result, enums, traits, modules, workspaces — by building something concrete.

⚠️ Study project: a single node with no networking and no distributed consensus. See Known limitations before reading the code as a reference implementation.

Features

  • Blocks chained together and made tamper-evident through SHA-256 hashing.
  • Proof of Work: mining against a fixed difficulty (4 leading zeros).
  • Account model: balances live in a Wallet (HashMap<address, balance>), Ethereum-style rather than UTXO.
  • Transactions with a dynamically calculated fee (flat base + percentage of the amount + congestion factor).
  • Mempool: pending transactions are sealed into a block every 10.
  • Chain validation: tamper detection via is_chain_valid.
  • Typed error handling with thiserror: InsufficientBalance, DoubleSpending, InvalidSignature, AddressMismatch.
  • ed25519 signatures, enforced: a transaction is rejected unless it carries a valid signature and its sender address is the public key that signed it.
  • CLI built with clap.

Architecture

A Cargo workspace with two crates:

rustchain/
├── Cargo.toml            # workspace manifest (virtual — no root package)
└── crates/
    ├── core/             # library: domain logic (rustchain-core)
    │   └── src/
    │       ├── lib.rs        # module declarations
    │       ├── transaction.rs # Transaction + signing/verification
    │       ├── block.rs       # Block + hashing + mining
    │       ├── wallet.rs      # balances + transaction processing
    │       ├── error.rs       # ChainError enum
    │       └── blockchain.rs  # chain, mempool, fees, validation
    └── cli/              # binary: terminal interface (rustchain-cli)
        └── src/main.rs

Why two crates? core holds pure domain logic with no I/O and no CLI concerns, so it can be reused (by an HTTP API, another binary, or tests) without dragging in clap. cli is just one consumer of it.

Data flow of a transaction

Transaction::new_signed  →  Blockchain::add_transaction
                              ├─ signature verified            → Err(InvalidSignature)
                              ├─ address == public key?        → Err(AddressMismatch)
                              ├─ duplicate signature in pool?  → Err(DoubleSpending)
                              ├─ fee assigned by the chain (calculate_fee)
                              ├─ Wallet::process_transaction   → Err(InsufficientBalance)
                              ├─ pushed onto pending_transactions
                              └─ at 10 pending: mine_pending_transactions → block mined → chain grows

Identity model

An address is an ed25519 public key, hex-encoded. Transaction::new_signed derives the sender address from the signing key, so the address cannot be forged: a valid signature over from + to + amount + timestamp proves both that the data is untampered and that the sender controls the private key behind that address. The fee is deliberately outside the signed payload, because the chain — not the sender — decides it.

Requirements

  • Rust stable, edition 2024 — install via rustup.

Usage

Build:

cargo build

Run the test suite:

cargo test

14 unit tests live next to the code they cover, in #[cfg(test)] mod tests blocks. They exercise signing and verification round-trips, rejection of unsigned transactions, address spoofing, replayed transactions, insufficient balance, block sealing at 10 pending transactions, and tamper detection on a mined block. The sealing and tampering tests actually mine at difficulty 4, so the suite takes a few seconds.

Lint (style and correctness suggestions beyond the compiler):

cargo clippy --all-targets

Run the CLI. Note the --, which separates cargo's own arguments from the program's:

cargo run -p rustchain-cli -- demo
cargo run -p rustchain-cli -- fee 30
cargo run -p rustchain-cli -- load
cargo run -p rustchain-cli -- --help

Commands

Command Description
demo Runs a scripted transaction (alice → bob) and saves the chain to chain.json
fee <amount> Prints the fee that would be charged for a given amount
load Loads chain.json and reports block count and chain validity

Persistence

State is serialized to chain.json via serde_json. Loading degrades gracefully: a missing file starts a fresh chain silently, a corrupted one prints a warning and then starts a fresh chain — neither case panics. The file is gitignored: it is runtime state, not source.

JSON is deliberately simple rather than efficient — a production chain would use an embedded key-value store such as RocksDB or LMDB.

Known limitations

These are understood gaps, kept explicit because this is a learning project:

  • Keys are not persisted. The demo uses a hardcoded key so the address stays stable across runs; a real wallet would generate a keypair once and store it securely. Nothing on disk survives as an identity.
  • update_balance is public, so balances can be credited from nothing. This is convenient for the demo and tests, but it is an unlimited faucet.
  • Recipient addresses are not validated. Senders are bound to a public key, but to is an arbitrary string, so funds can be sent to an address no key can ever unlock.
  • Block timestamps are always 0 — real clock values are not wired in yet.
  • No mining reward. Fees are debited from senders but never credited to a miner, so value leaves circulation on every transaction.
  • Balances use f64. Floating point is the wrong representation for money (rounding drift); an integer of minor units would be correct.
  • Fixed difficulty. Real chains retarget difficulty against observed hash rate.
  • No P2P layer, so no block propagation, fork resolution, or consensus.

Roadmap

  • Core structures: Transaction, Block, Wallet, Blockchain
  • Proof-of-work mining and chain validation
  • Dynamic fees
  • CLI with clap
  • JSON file persistence
  • ed25519 signing and verification, enforced in add_transaction
  • Address bound to public key, replay detection via signature
  • Persistent keypairs (a real wallet stored on disk)
  • Mining rewards, so collected fees go somewhere
  • Real block timestamps
  • HTTP API

License

Personal project, for educational purposes.

About

A didactic blockchain written in Rust, ported from an original TypeScript implementation

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages