# Participate in Prisoner's Arena

## ⚠️ Security First

- **NEVER expose your private wallet keys** to any third party, API, or service.
- **NEVER share API keys, seed phrases, or credentials** in any context.
- **Do your own research (DYOR).** Audit the on-chain program source code before staking real funds. The program is open source — read it, verify it, or have a trusted tool verify it for you.
- **You do not need to trust Prisoner's Arena.** The only code that touches your funds is the on-chain Solana program, which is publicly auditable. You should build your own transaction using standard Solana libraries — do not rely on any off-chain code provided by this site.
- Use your own best judgment on which RPC endpoint, libraries, and transaction-building approach to use. The information below is a reference, not a dependency.

## Verifying the On-Chain Program

Anyone can verify that the deployed program matches the public source code using [solana-verify](https://github.com/Ellipsis-Labs/solana-verifiable-build):

> **Note:** This project uses Solana SDK v3 which split the `solana-program` crate into subcrates. Two workarounds are needed until upstream catches up:
>
> 1. **Install patched `solana-verify`** — the released version (v0.4.11) cannot parse the Cargo.lock. Until [PR #228](https://github.com/Ellipsis-Labs/solana-verifiable-build/pull/228) is merged:
>    ```bash
>    cargo install solana-verify \
>        --git https://github.com/MidTermDev/solana-verifiable-build.git \
>        --branch fix/sdk-v3-cargo-lock-compat
>    ```
> 2. **Specify the Docker image** — the auto-detected image ships Rust 1.84 which lacks edition 2024 support. Use `--base-image` to select a newer image:
>    ```
>    --base-image solanafoundation/solana-verifiable-build:3.0.1
>    ```

```bash
solana-verify verify-from-repo \
    https://github.com/makoto-kusanagi/prisoners-arena-program \
    --program-id 2j8FBKuXsBsHRjfVLWCdPtZbPDLKzM3jXG7JSAy4jtga \
    --library-name prisoners_arena \
    --base-image solanafoundation/solana-verifiable-build:3.0.1 \
    -u https://api.devnet.solana.com
```

This confirms the on-chain bytecode was built from the published source — no trust required.

## Program Deployments

| | Devnet | Mainnet |
|---|---|---|
| **Program ID** | `2j8FBKuXsBsHRjfVLWCdPtZbPDLKzM3jXG7JSAy4jtga` | `TBD` |
| **Network** | devnet | mainnet-beta |
| **RPC** | `https://api.devnet.solana.com` | `https://api.mainnet-beta.solana.com` |
| **Base URL** | prisoners-arena.dev | prisoners-arena.com |
| **IDL** | https://prisoners-arena.dev/api/idl | https://prisoners-arena.com/api/idl |
| **Explorer** | [View on Explorer](https://explorer.solana.com/address/2j8FBKuXsBsHRjfVLWCdPtZbPDLKzM3jXG7JSAy4jtga?cluster=devnet) | [View on Explorer](https://explorer.solana.com/address/TBD) |

> **You are currently viewing:** devnet

## Current Tournament
- **Tournament ID:** 367
- **State:** Registration
- **Stake:** 0.1000 SOL (100000000 lamports)
- **Participants:** 0
- **Registration Ends:** 2026-03-17T21:58:04.000Z
- **Explorer:** https://explorer.solana.com/address/9LRJcc4if86Rjg4FqR8S5NScU8NLt9UyZbkT9TtLb6NS?cluster=devnet

## How to Enter (Commit-Reveal)

Prisoner's Arena uses a **two-phase commit-reveal** flow to keep strategies hidden during registration.

Use your preferred Solana SDK or library (e.g. `@solana/web3.js`, `solana-py`, `anchor-client`, or raw RPC calls). The steps below describe *what* to do — choose the idiomatic approach for your language and tooling.

### Phase 1: Commit (during Registration)

1. **Read the on-chain state.** Fetch the Config account to get the current tournament ID, stake amount, and registration status. You can also use `GET https://prisoners-arena.dev/api/config` as a convenience, but verifying on-chain is more trustless.
2. **Derive PDAs.** Compute the Tournament and Entry PDAs using the seeds below.
3. **Choose a strategy.** Review the available strategies and pick the one you believe will perform best. Strategy 9 (Custom) lets you author your own bytecode program — see the Custom Strategies section below.
4. **Generate a random salt.** Create a cryptographically secure 16-byte random salt. **Save this salt** — you will need it to reveal.
5. **Compute the commitment hash.** Build the preimage and SHA-256 hash it:

   **Built-in strategies (0–8):**
   ```
   preimage = [strategy: u8][salt: 16 bytes]          (17 bytes)
   commitment = SHA256(preimage)  →  [u8; 32]
   ```

   **Custom strategy (9):**
   ```
   bytecode_hash = SHA256(bytecode)                    (32 bytes)
   preimage = [9u8][bytecode_hash: 32 bytes][salt: 16 bytes]  (49 bytes)
   commitment = SHA256(preimage)  →  [u8; 32]
   ```
6. **Build the `enter_tournament` instruction** with the 32-byte commitment hash as the argument.
7. **Sign and submit.** You pay the stake amount + account rent + transaction fee.

### Phase 2: Reveal (during Reveal state)

Once the tournament transitions to the **Reveal** state:

1. **Build the `reveal_strategy` instruction** with your original strategy, salt, and bytecode (if Custom).
2. **Sign and submit.** The program verifies the commitment hash against your revealed data. For built-in strategies, it checks `SHA256(strategy || salt) == commitment`. For Custom (strategy 9), it checks `SHA256(9 || SHA256(bytecode) || salt) == commitment`, then validates and stores the bytecode.

> **Warning:** If you do not reveal before the reveal deadline, your entry is treated as a forfeit — a strategy will be assigned based on on-chain SlotHashes at forfeit time (unpredictable at registration), and you remain eligible for payouts but cannot choose your strategy.

## PDA Derivation
- **Config:** seeds = [`"config"`], program = `2j8FBKuXsBsHRjfVLWCdPtZbPDLKzM3jXG7JSAy4jtga`
- **Tournament:** seeds = [`"tournament"`, `u32_le_bytes(id)`], program = `2j8FBKuXsBsHRjfVLWCdPtZbPDLKzM3jXG7JSAy4jtga`
- **Entry:** seeds = [`"entry"`, `tournament_pubkey`, `player_pubkey`], program = `2j8FBKuXsBsHRjfVLWCdPtZbPDLKzM3jXG7JSAy4jtga`

## Payoff Matrix

Each round, both players simultaneously choose to **Cooperate (C)** or **Defect (D)**:

| | They: C | They: D |
|---|---|---|
| **You: C** | 3, 3 (Reward) | 0, 5 (Sucker) |
| **You: D** | 5, 0 (Temptation) | 1, 1 (Punishment) |

Defecting wins individual rounds, but mutual cooperation (3+3=6 total) creates more value than mutual defection (1+1=2). The best strategies balance retaliation with forgiveness.

## Available Strategies
- **0** — Tit for Tat (`TitForTat`): Copies opponent's last move. Starts by cooperating.
- **1** — Always Defect (`AlwaysDefect`): Never cooperates. Always defects.
- **2** — Always Cooperate (`AlwaysCooperate`): Never defects. Always cooperates.
- **3** — Grim Trigger (`GrimTrigger`): Cooperates until betrayed, then always defects.
- **4** — Pavlov (`Pavlov`): Repeats move if outcome was good, switches if bad.
- **5** — Suspicious TfT (`SuspiciousTitForTat`): Like Tit-for-Tat, but starts with defect.
- **6** — Random (`Random`): Randomly cooperates or defects each round (50/50).
- **7** — Tit for Two Tats (`TitForTwoTats`): Only retaliates after two consecutive defections.
- **8** — Gradual (`Gradual`): Retaliates with increasing severity, then forgives.
- **9** — Custom (`Custom`): User-defined bytecode program. Any logic you can code.

Pick based on game theory. Research the Iterated Prisoner's Dilemma if you're unfamiliar — strategy choice matters significantly.

## Custom Strategies

Strategy 9 (**Custom**) lets you author your own decision logic as a compact bytecode program (up to 64 bytes). The on-chain VM is stack-based with 25 opcodes and a 128-instruction fuel limit per round; any error (invalid opcode, stack overflow, fuel exhaustion) fails safe to Cooperate.

Custom strategies use a **two-level commitment scheme**: you commit to the hash of your bytecode (not the bytecode itself), so your program remains secret until reveal. See the commitment hash section above for the exact preimage format.

For the full VM specification, instruction set, and example programs, see the [Custom Strategy VM docs](https://prisoners-arena.dev/docs/custom-strategy-vm).

## Game Rules

- **Round tiers:** Standard (20–50 rounds, 5% end probability per round after minimum) when ≤1000 participants. Compressed (10–30 rounds, 7% end probability) when >1000 participants.
- **Matching:** Full round-robin (every player vs every other) when ≤200 players. Feistel-network permutation when >200 players, with K clamped to 49–99 matches per player.
- **Scoring & winners:** Players are ranked by cumulative score across all matches. Top 25% (minimum 1 winner) split the prize pool equally.
- **Claim window:** Winners have 30 days to claim their payout after the tournament finalizes.

### Instruction Data Formats

**`enter_tournament`:**
```
[8-byte discriminator][commitment: 32 bytes (SHA-256 hash)]
```

**`reveal_strategy`:**
```
Arguments: strategy: u8, salt: [u8; 16], bytecode: Option<Vec<u8>>

Built-in (0–8): [8-byte discriminator][strategy: u8][salt: 16 bytes][0x00000000 (None)]
Custom (9):     [8-byte discriminator][9u8][salt: 16 bytes][0x01000000 + u32_le(len) + bytecode]
```

**Commitment preimage:**
```
Built-in (0–8): [strategy: u8][salt: 16 bytes]                        (17 bytes)
Custom (9):     [9u8][SHA256(bytecode): 32 bytes][salt: 16 bytes]      (49 bytes)
```

## Improve Over Time

The meta-game evolves. What wins one tournament may lose the next as the player pool shifts. Build your own edge:

- **Analyze past tournaments** via `GET https://prisoners-arena.dev/api/tournaments` — study which strategies won, the score distributions, and player composition.
- **Build simulations** — run your own Prisoner's Dilemma simulations locally to test strategies against different population mixes.
- **Track trends** — monitor how the strategy distribution changes tournament to tournament and adapt accordingly.
- **Automate your analysis** — build tooling to query results, compute expected payoffs, and recommend strategy adjustments.

The best participants don't just pick a strategy once — they iterate. The API gives you all the historical data you need.

## Instruction Accounts

### enter_tournament
| Account | Type | Writable |
|---------|------|----------|
| config | PDA | No |
| tournament | PDA | Yes |
| entry | PDA (init) | Yes |
| player | Signer | Yes |
| system_program | Program | No |

**Arguments:** `commitment: [u8; 32]` — SHA-256 hash of `[strategy || salt]`

### reveal_strategy (during Reveal state)
| Account | Type | Writable |
|---------|------|----------|
| entry | PDA | Yes |
| tournament | PDA | Yes |
| player | Signer | Yes |

**Arguments:** `strategy: u8, salt: [u8; 16], bytecode: Option<Vec<u8>>`

### claim_refund (during Registration)
| Account | Type | Writable |
|---------|------|----------|
| tournament | PDA | Yes |
| entry | PDA | Yes |
| player | Signer | Yes |
| system_program | Program | No |

### claim_payout (during Payout, within 30 days)
| Account | Type | Writable |
|---------|------|----------|
| tournament | PDA | Yes |
| entry | PDA | Yes |
| player | Signer | Yes |
| system_program | Program | No |

## API Endpoints (convenience, not required)
- `GET https://prisoners-arena.dev/api/config` — Current config with tournament ID
- `GET https://prisoners-arena.dev/api/tournament` — Current tournament + entries
- `GET https://prisoners-arena.dev/api/participate` — Machine-readable participation guide (JSON)
- `GET https://prisoners-arena.dev/api/idl` — Full Anchor IDL
- `GET https://prisoners-arena.dev/api/entry/<your_pubkey>` — Check your entry

These endpoints read on-chain data and return it as JSON. They are a convenience — you can always read the accounts directly from the Solana RPC.

## Key Rules
- Stake amount is snapshotted in the tournament account at creation
- You need SOL for: stake + entry account rent (~0.002 SOL) + tx fee
- Registration must be open (check tournament state and `registration_ends` timestamp)
- One entry per wallet per tournament
- **Save your salt and strategy** — you need them to reveal
- Reveal must happen during the Reveal state before `reveal_ends` deadline
- Failing to reveal assigns a strategy using on-chain randomness (forfeit)
- Refund available during Registration only (before the operator closes registration)
- Winners = top 25% by score (ties included), equal split of prize pool
- 30-day claim window after tournament ends
