← Course home Live Sandbox Blockchain — Companion to the Capstone

MineRace — Live Blockchain Sandbox

A shared, live, multi-player blockchain running 24/7. Plug your own wallet, transactions, and miner into it in any language. Open competition, no grading — just an excuse to ship code against a real chain and climb the leaderboard.

Open competition 🌐 24/7 live chain Companion to Part 1 Project
Live now at minerace.mehditmimi.com — the dashboard shows the current chain height, difficulty, reward, and leaderboard in real time.

This is the open companion to the MineRace capstone. The capstone is the from-scratch build; this is the live arena where your code — or any new code, in any language — meets a real shared chain.

📌 Welcome

The practical companion

Welcome. This is the practical companion to the blockchain capstone. You've built your own MineRace clone from scratch — now you're going to put your code (or new code, in any language) against a shared, live, multi-player chain running 24/7.

You can mine, send coins, trade with classmates, and climb the leaderboard. It's not a graded assignment — it's an open competition that runs for the rest of the course. Build whatever client you like.

What you get from us

Resource URL
Live dashboard (read-only explorer) minerace.mehditmimi.com
Technical spec (the contract your code must follow) STUDENT_GUIDE.md
Leaderboard JSON /api/leaderboard

That's it. No starter code, no boilerplate, no language constraint. What you build is up to you.

🛠️ What you build

Three things, your order

Three things — order is up to you, but the suggestion is to walk before you run:

🔐

1. A wallet

A program that generates a secp256k1 keypair, stores the private key safely on your machine, and exposes your public key (the “address”) for receiving coins. No registration step — your public key is your account.

💸

2. A transaction tool

Code that signs a transaction (from, to, amount) with your private key and POSTs it to /api/transaction. The server validates the signature, checks your balance, and adds it to the mempool. When a miner includes it in a block, it's confirmed.

⛏️

3. A mining bot

Code that fetches /api/challenge, assembles a candidate block (must include exactly one reward transaction paying you the mining reward), searches for a nonce such that the block hash starts with N hex zeros, and POSTs the result to /api/submitBlock. First miner to land block #N wins it.

Everything you need to know about how — payload shapes, hash formula, signature format, error messages — lives in the STUDENT_GUIDE.md. Read it once before you start coding.

🎯 Suggested path

Suggested milestones

There's no schedule — go at your own pace. Roughly in order of escalating difficulty:

  1. Be visible — generate a wallet locally. Verify your address is real: GET /api/validate/<your-pubkey> should return {"valid": true}.
  2. Read the chain — pull /api/chain, /api/balance/<addr>, /api/leaderboard, /api/mempool from your code. Print them nicely.
  3. Receive your first coins — easiest path: ask a classmate who already mined to send you some. Or just mine yourself (next step).
  4. Mine a block — your first successful block submission. The server's mining reward (currently 50 coins) drops into your wallet. Refresh the dashboard — you're on the leaderboard.
  5. Send a transaction — sign a tx with your key, POST it, watch it appear in /api/mempool, wait for some miner (you, a classmate, or a server bot) to include it in a block. Re-check /api/balance/<recipient> — they have your coins.
  6. Compete — make your miner faster. Run multiple worker threads. Pack pending mempool tx into your blocks. Re-fetch the challenge on every stale-block rejection. Tune your parallelism.
💰 Economy

The economy

  • Mining reward: 50 coins per block (subject to live adjustment by the instructor; always check /api/difficulty).
  • Difficulty: hash must start with N hex zeros. Adjusted dynamically by the server.
  • No fees: transactions cost nothing. Miners get only the coinbase reward.
  • No faucet: the only way to get your first coins is to mine or convince a classmate to send you some.
  • No tx supply: coins are minted only by mining. Total supply grows by 50 every block.
  • Server bots: 3 slow bots (“Bot-Paris”, “Bot-Tokyo”, “Bot-NYC”) keep the chain alive at off-hours. They're real ECDSA wallets and they follow the same rules you do.
🏆 Etiquette

Tournament rules

Open competition. No formal grading. Just etiquette so it stays fun:

  • One wallet per person. Pick a keypair, stick with it — that's your identity on the leaderboard. (You're free to use multiple in private for testing.)
  • Don't share your private key publicly. Treat it like a password. Anyone with it can drain your wallet.
  • Don't DDoS the server. Rate limits are in place: 60 tx/min, 300 block-submissions/min, 10 AI-chat/min per IP. Stay well under and you're fine.
  • Mining hardware: CPU mining is the spirit. GPU/ASIC is technically allowed but discouraged — be a sport.
  • Trading is encouraged. Build mini-economies with classmates: pay each other for favors, trade for solutions, run a betting market. Whatever's fun.
📢 Show it off

How to brag

  • Leaderboard — the live dashboard shows top miners. Screenshot it.
  • Address detail — click any address on the dashboard to see its blocks mined, balance, and full transaction history. Great proof for “look how much I mined.”
  • Direct dashboard link — when you click your address in the dashboard, the URL changes (or you can copy your full pubkey and search for it). Share that link.
🐛 Debug first

Common gotchas (read before debugging)

These bite ~90% of students. Save yourself an hour:

Hash mismatch

The most common failure on submitBlock. Causes:

  • Wrong JSON field order in transactions. The server uses JSON.stringify, which serializes in insertion order. Build your tx objects with keys in this exact order: from, to, amount, signature. Anything else and the server's recomputed hash won't match yours.
  • Pretty-printed JSON. Use compact serialization (no whitespace, no indent). In Python: json.dumps(x, separators=(',', ':')). In JS: plain JSON.stringify(x).
  • null vs missing field. The reward tx's signature must be the literal null, not omitted.

Invalid signature

  • The server hashes from + to + amount as a string concatenation (no separators, no JSON). Sign that hash, not anything else.
  • Signature must be DER-encoded, hex. In JS elliptic: sig.toDER('hex'). In Python ecdsa: sign_digest(..., sigencode=sigencode_der).hex().

Invalid 'to' address

Your to field isn't a valid secp256k1 uncompressed pubkey. It must be:

  • 130 hex characters
  • Start with "04" (uncompressed prefix)
  • The (X, Y) coordinates must lie on the secp256k1 curve

Pre-check with GET /api/validate/<addr> before you sign.

Python float vs JS number

JS treats 5 and 5.0 as the same number — (5.0).toString() === "5". Python doesn't: str(5.0) === "5.0". If you sign over "5.0" but send JSON 5.0, the server hashes "5" and your signature fails.

Fix: always use integers for whole-coin amounts. In Python: amount = 5, not amount = 5.0.

"Insufficient proof of work"

Your hash doesn't have enough leading zeros. Re-read the difficulty from the challenge response — it can change between attempts (dynamic adjustment).

"Stale block: index mismatch"

Someone else got there first. Refetch /api/challenge and start over. This is normal and expected during contention.

💻 Any language

Per-language quick start

You can use anything. The spec is language-agnostic. Here are the most common stacks:

Stack Crypto library
JavaScript / Node.js npm i elliptic — same one the server uses
Python pip install ecdsa — beware the 04 prefix gotcha (libraries return X‖Y without it) and the str(5.0) gotcha (cast whole amounts to int)
Go github.com/btcsuite/btcd/btcec/v2
Rust secp256k1 crate
Java / Kotlin BouncyCastle (org.bouncycastle.crypto.params.ECDomainParameters)
C# / .NET BouncyCastle.NetCore

Code examples for JS and Python are in STUDENT_GUIDE.md §2 + §5. Treat them as references; rewrite in your language of choice.

📥 Optional

What to hand in (if anything)

This is not a graded assignment. But if you want me to acknowledge your work, send a quick message with:

  • Your wallet address (the public part — never the private key)
  • A link to your code (GitHub, GitLab, whatever)
  • A note on what you built (CLI? GUI? Telegram bot? Mobile app?)

You can use this in your portfolio later. “I wrote a CPU miner in Rust that landed N blocks on a live blockchain” is a great line.

FAQ

FAQ

Can I run my miner 24/7 on a cloud VM?

Yes. The server doesn't care where the requests come from. It rate-limits per IP, so don't run 50 bots from the same address.

Can I mine with a friend's address?

Technically yes — but the friend gets the rewards. Useful for cooperative challenges. Don't do this if you're trying to climb the leaderboard fairly.

Will the chain ever be wiped?

Possibly between course terms, with advance notice. The instructor can announce a “season reset” — wallets carry over but balances do not.

Is the AI agent available?

Yes — POST /api/chat with {"message": "how many blocks?"}. Replies take 10–30 seconds because it's a 3B local model. Rate limited to 10 requests/minute per IP.

What happens if the server goes down?

Restarts wipe in-memory mempool but not the chain. Your mined blocks and balances persist. Just retry submissions.

How long does this run?

While the course is active. The instructor will give notice before tearing down the box.

🎉

Have fun. Be a sport.

Win some blocks. The leaderboard is at minerace.mehditmimi.com — we'll see you there.