Skip to content

Het2239/ConsensOS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Blockchain Simulator

EGC 301P — Operating Systems Lab Mini Project

A multi-client blockchain simulator built in C demonstrating core OS concepts through a realistic blockchain-inspired architecture.


OS Concepts Demonstrated

Concept Where
POSIX Threads Handler, miner, and mempool manager threads
Mutex + Condition Variables Mempool queue producer-consumer
Semaphores Miner race and wakeup on new transactions
Named Pipe (FIFO) / IPC handler.c → /tmp/bc_tx_pipe → mempool.c
File Locking (fcntl) ledger.dat and users.dat readers-writers
Singleton Instance Lock data/server.lock prevents duplicate servers
TCP Socket Programming Multi-client server, full-duplex text protocol
select() Non-Blocking I/O Client async push notifications (NOTIFY)
Proof of Work (PoW) CPU nonce search before block commit
Coinbase Transactions Miners earn BLOCK_REWARD per block mined
Merkle Tree Transaction integrity + inclusion proofs
Role-Based Access Control guest / user / miner permissions in auth.c

Build

make          # builds both server and client
make clean    # removes binaries and object files

Requirements: GCC, POSIX (Linux), pthreads


Run

Terminal 1 — Server:

./server/server <port> <block_size> [difficulty]

# example: port 8891, block fills at 3 transactions, PoW difficulty 2
./server/server 8891 3 2

Miners are not pre-started at launch. They join dynamically when a user with role miner logs in.

Terminal 2+ — Client(s):

./client/client <server_ip> <port>

# example:
./client/client 127.0.0.1 8891

Client Menu

1. Register               — create account (role: guest / user / miner)
2. Login                  — authenticate
3. Send coins             — transfer to a wallet address (user/miner)
4. View my balance        — check wallet balance
5. View blockchain        — print all blocks and transactions
6. Verify transaction     — confirm a tx is in a block
7. Lookup wallet          — get full wallet address by username
8. Verify Merkle proof    — inclusion proof for a transaction
9. Logout
M. Mempool stats          — pending tx count + active miner (miner only)
F. Faucet                 — claim 100 testnet coins (user/miner)
0. Exit

Architecture

Clients ──TCP sockets──► Auth module
                              │
                     Client handler threads (1 per connection)
                         │              │
                   FIFO (IPC)       fcntl RDLCK
                         │              │
                  Mempool manager    ledger.dat
                         │
              sem_post × N_active_miners (genuine race)
                         │
              ┌──────────┼──────────┐
           Miner 0    Miner 1    Miner N      ← spawned on miner login
           (coinbase)  (coinbase)  (coinbase)
              └──────────┼──────────┘
                   fcntl WRLCK
                         │
                     ledger.dat  (append-only)

Miner Behavior (Dynamic, Login-Based)

  • Join: When a user with role=miner logs in, a miner thread is spawned and their wallet is registered to the slot. Mining begins immediately.
  • Race: When a new transaction enters the mempool, race_sem is posted once per active miner — all wake up and compete via active_miner mutex. First to acquire the mutex mines next.
  • Coinbase: Every mined block automatically prepends a coinbase → miner_wallet transaction worth BLOCK_REWARD = 10 coins.
  • Merkle root: Computed from all transactions (including coinbase) before PoW starts — tampering with any tx invalidates both the Merkle root and the block hash.
  • Wait phase: Active miner waits up to 15 s for more txs to fill the block. Mines immediately when full or on timeout.
  • Leave: When a miner disconnects, should_stop=1 is set. Their thread exits cleanly; any popped-but-unmined transactions are returned to the mempool.

File Formats

data/ledger.dat — one block per line (MERKLE format):

<idx>|<prev_hash>|<hash>|<merkle_root>|<ts>|<miner_id>|<nonce>|<tx_count>|<tx1>|...

Each <txN>: tx_id,from_wallet,to_wallet,amount,timestamp

Backward compatible: old blocks without merkle_root are parsed transparently.

data/users.dat — one user per line:

<username>|<password_hash>|<wallet_addr>|<role>

Project Structure

OS project/
├── server/
│   ├── server.c      main, socket accept loop, global state init
│   ├── state.h       all shared structs, constants, ServerState
│   ├── auth.c/h      login, register, role permission checks
│   ├── mempool.c/h   circular queue, FIFO reader thread, race_sem post
│   ├── miner.c/h     dynamic miner threads, PoW, coinbase, Merkle root
│   ├── ledger.c/h    append-only ledger, fcntl locking, Merkle verify
│   ├── handler.c/h   client handler thread, VERIFY_MERKLE, miner spawn
│   └── hash.c/h      djb2 hashing, compute_merkle_root, build_merkle_proof
├── client/
│   └── client.c      TCP client with CLI menu, select() NOTIFY loop
├── data/             created at runtime
│   ├── ledger.dat    blockchain ledger (always reset on server start)
│   ├── users.dat     registered users
│   └── server.lock   singleton process lock
├── Makefile
├── README.md
└── PROJECT_REPORT.md

Key Commands (server protocol)

Command Args Auth
REGISTER username password role public
LOGIN username password public
SUBMIT to_wallet amount user / miner
BALANCE user / miner
FAUCET user / miner
LOOKUP username public
VERIFY tx_id public
VERIFY_CHAIN public
VERIFY_MERKLE tx_id public
VIEW_CHAIN public
MEMPOOL_STATS miner only
QUIT public

Typical Session

# Register a miner user
Register → username: alice  password: pw123  role: miner
# Alice logs in → miner thread spawned automatically, starts competing

# Register a regular user
Register → username: bob  password: pw123  role: user
# Bob logs in → no miner thread

# Bob claims faucet coins (goes via FIFO → mempool → Alice mines it)
FAUCET → OK  tx_id=abc123...  coins appear after mining

# Bob sends coins to Alice
LOOKUP alice → Full wallet: 6865108148c207f2d531ce2e1568ca59
SUBMIT 6865108148c207f2d531ce2e1568ca59 20
# Live ticker appears, waiting for Alice's miner to mine the block
# *** TRANSACTION CONFIRMED! *** block=#3  elapsed=4.2s

# Verify Merkle inclusion proof
VERIFY_MERKLE abc123...
# → proof path printed, Result: VALID ✓

# Check Alice's balance (includes coinbase rewards)
BALANCE → balance=30.0000  (10 coinbase + 20 from Bob)

About

A concurrent distributed ledger system built from scratch in C, implementing a multi-miner blockchain with socket-based client access, POSIX file locking, named pipe IPC, and role-based authorization.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors