# MineRace — Live Blockchain Sandbox

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) | https://minerace.mehditmimi.com |
| **Technical spec** (the contract your code must follow) | https://minerace.mehditmimi.com/STUDENT_GUIDE.md |
| **Leaderboard JSON** | https://minerace.mehditmimi.com/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 — 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**](STUDENT_GUIDE.md). Read it once before you start coding.

---

## 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.

---

## 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.

---

## 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.

---

## 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.

---

## 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.

---

## 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.Cryptography` (or `Portable.BouncyCastle` — the older `BouncyCastle.NetCore` is archived) |

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

---

## 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

**Q: 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.

**Q: 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.

**Q: 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.

**Q: Is the AI agent available?**
Yes — `POST /api/chat` with `{"message": "how many blocks?"}`. Replies usually take 20–60 seconds because it's a small local LLM (Ollama, model configurable on the server). Rate limited to 10 requests/minute per IP.

**Q: 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.

**Q: 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.
