Metadata-Version: 2.4
Name: coinrandom
Version: 1.0.1
Summary: True random numbers sourced from live cryptocurrency market data
Author-email: dglst <woo9910203626@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/LETUED/coinrandom
Project-URL: Repository, https://github.com/LETUED/coinrandom
Project-URL: Bug Tracker, https://github.com/LETUED/coinrandom/issues
Project-URL: Changelog, https://github.com/LETUED/coinrandom/blob/main/CHANGELOG.md
Keywords: random,entropy,cryptocurrency,bitcoin,randomness,cryptography,DRBG,verifiable-random,proof
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.28
Requires-Dist: argon2-cffi>=21.0
Provides-Extra: superheavy
Requires-Dist: numpy>=1.24; extra == "superheavy"
Requires-Dist: scipy>=1.10; extra == "superheavy"
Provides-Extra: dev
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Requires-Dist: pytest; extra == "dev"

# coinrandom

[한국어](README.ko.md) | English

> True random numbers sourced from live cryptocurrency market data.

```python
import coinrandom

coinrandom.random()        # 0.7182818...
coinrandom.randint(1, 100) # 42
coinrandom.choice(["a", "b", "c"])
```

---

## Why coinrandom?

Cryptocurrency markets trade 24/7 globally. At the tick level — individual trade prices, quantities, timestamps, and buyer/seller direction — the data is highly unpredictable. The Efficient Market Hypothesis (EMH) says no one can consistently predict short-term market movements. **coinrandom uses this unpredictability as an entropy source.**

### Trust Model

> Even with the full source code published, no one can predict the output in advance — because no one can predict the coin market.

This is an application of **Kerckhoffs's principle**: security depends on the unpredictability of the market, not on keeping the algorithm secret. Each value generated by Heavy/SuperHeavy comes with a `RandomProof` — a verifiable audit trail showing exactly which market data produced the result.

**Honest limits:** coinrandom provides *computational security* (like AES/RSA), not *information-theoretic security* (like Chainlink VRF). The trust model is economic, not mathematical. For cryptographic key generation, use `secrets`. For smart contract RNG, use Chainlink VRF.

---

## Installation

```bash
pip install coinrandom                     # Light + Heavy
pip install "coinrandom[superheavy]"       # + SuperHeavy (numpy, scipy)
```

No API keys. No configuration.

---

## Three Tiers

| Tier | Speed | Entropy source | Proof | Use case |
|------|-------|---------------|-------|----------|
| **Light** | ~1ms | Binance tick + Argon2 | No | High-volume generation |
| **Heavy** | ~2s | 3 exchanges + ETH + BTC block hash + Argon2 | Yes | Raffles, NFT mints, DAO votes |
| **SuperHeavy** | ~30s | Portfolio-optimized coins + Heavy pipeline (ETH + BTC) | Yes | Maximum entropy, auditable |

All tiers return the same API — drop-in replacement for Python's `random` module.

---

## Usage

### Function Reference

| Function | Signature | Description |
|----------|-----------|-------------|
| `random()` | `() → float` | Uniform float in [0.0, 1.0) |
| `uniform(a, b)` | `(float, float) → float` | Uniform float in [a, b] |
| `randint(a, b)` | `(int, int) → int` | Uniform integer in [a, b] inclusive |
| `choice(seq)` | `(Sequence) → Any` | One random element from a sequence |
| `choices(seq, k)` | `(Sequence, int) → list` | k elements with replacement |
| `sample(seq, k)` | `(Sequence, int) → list` | k elements without replacement |
| `shuffle(seq)` | `(MutableSequence) → None` | In-place shuffle |
| `gauss(mu, sigma)` | `(float, float) → float` | Normal distribution sample |
| `random_with_proof()` | `() → RandomProof` | Heavy / SuperHeavy only — value + audit trail |

All functions have async variants prefixed with `a`: `arandom()`, `arandint()`, `arandom_with_proof()`, etc.

---

### Light (default)

```python
import coinrandom

# Basic
coinrandom.random()                        # 0.7182818...  float in [0.0, 1.0)
coinrandom.uniform(1.5, 9.5)              # 6.234...      float in [a, b]
coinrandom.randint(1, 6)                  # 4             integer in [a, b] inclusive
coinrandom.gauss(mu=0.0, sigma=1.0)       # -0.312...     normal distribution

# Sequences
coinrandom.choice(["rock", "paper", "scissors"])   # pick one
coinrandom.choices(range(1, 7), k=5)               # roll dice 5 times (with replacement)
coinrandom.sample(range(1, 46), k=6)               # lotto numbers (no duplicates)

lst = list(range(1, 11))
coinrandom.shuffle(lst)                            # in-place shuffle

# Practical: raffle — pick 3 winners from participants
participants = ["Alice", "Bob", "Carol", "Dave", "Eve"]
winners = coinrandom.sample(participants, k=3)

# Practical: 5% probability event
if coinrandom.random() < 0.05:
    print("rare drop!")
```

### Heavy — with proof

Each call fetches live data from 3 exchanges + ETH + BTC block hashes, then applies Argon2id.
Returns a `RandomProof` with a full audit trail.

```python
from coinrandom import heavy

# Simple usage — same API as Light
val = heavy.random()
n   = heavy.randint(1, 100)

# Practical: auditable raffle
participants = ["Alice", "Bob", "Carol", "Dave", "Eve"]
proof = heavy.random_with_proof()
winner = participants[int(proof.value * len(participants))]

print(winner)
print(proof.value)               # 0.3571428...
print(proof.block_hashes)        # {"ETH": "0xabc123...", "BTC": "000000000000..."}
print(proof.block_hashes["ETH"])
print(proof.block_hashes["BTC"])
print(proof.exchanges)           # [{"exchange": "binance", "symbol": "BTCUSDT", ...}, ...]
print(proof.final_hash)          # SHA-256 of the Argon2-stretched entropy
print(proof.timestamp)           # "2026-05-17T09:00:00.123456"

# NFT mint order — shuffle with proof
token_ids = list(range(1, 10001))
for _ in range(len(token_ids)):
    proof = heavy.random_with_proof()
    # use proof.value to drive each swap step, saving proofs for audit
```

### SuperHeavy — portfolio-optimized entropy

Runs inverse Markowitz optimization to select the **least-correlated coins** as entropy sources before executing the Heavy pipeline.

```python
from coinrandom import superheavy  # requires: pip install "coinrandom[superheavy]"

val   = superheavy.random()
proof = superheavy.random_with_proof()

print(proof.value)
print(proof.selected_symbols)       # coins selected by inverse portfolio optimization
print(proof.correlation_matrix)     # correlation matrix of candidates
print(proof.optimization_result)    # scipy SLSQP result
print(proof.block_hashes)           # {"ETH": "...", "BTC": "..."}
print(proof.final_hash)
```

### Saving proof as JSON

`RandomProof` and `SuperProof` are plain dataclasses — serialize with the standard library:

```python
import dataclasses, json

proof = heavy.random_with_proof()

with open("proof.json", "w") as f:
    json.dump(dataclasses.asdict(proof), f, indent=2)
```

### Async API

All functions have async variants prefixed with `a`.

```python
import asyncio
import coinrandom
from coinrandom import heavy, superheavy  # superheavy requires [superheavy] extra

async def main():
    # Light
    val = await coinrandom.arandom()
    n   = await coinrandom.arandint(1, 100)
    c   = await coinrandom.achoice(["a", "b", "c"])
    lst = [1, 2, 3]
    await coinrandom.ashuffle(lst)

    # Heavy
    val   = await heavy.arandom()
    proof = await heavy.arandom_with_proof()
    print(proof.block_hashes)

    # SuperHeavy
    val   = await superheavy.arandom()
    proof = await superheavy.arandom_with_proof()
    print(proof.selected_symbols)

asyncio.run(main())
```

Async methods offload blocking I/O to a thread pool via `asyncio.run_in_executor` — no new dependencies.

---

## Design Principles

1. **No API keys** — works out of the box with `pip install`
2. **Uniform API** — every tier exposes the same functions as `random`
3. **No Mersenne Twister** — custom HashDRBG (SHA-512 counter-based) seeded from coin market data and OS hardware entropy
4. **Open-source safe** — Kerckhoffs's principle: publishing the algorithm doesn't compromise security
5. **Intentionally heavy** — Heavy/SuperHeavy: each call runs the full entropy pipeline. "Slow = costly to manipulate."

---

## Internals

```
coinrandom/
├── __init__.py          # Light tier as default API
├── core.py              # fetch_binance_entropy, mix_entropy
├── proof.py             # RandomProof, SuperProof dataclasses
├── light/               # HashDRBG + Argon2 (t=1, m=8MB) reseed cache
├── heavy/               # 3 exchanges parallel + ETH block hash + Argon2 (t=4, m=64MB)
└── superheavy/          # Inverse portfolio optimization → Heavy pipeline
```

### HashDRBG

Custom SHA-512 counter-based DRBG. No `import random` anywhere in the codebase.

```python
# Simplified
state = argon2(mix_entropy(coin_data, os.urandom(32)))
output = sha512(state + counter)  # per call
```

### Manipulation resistance

Heavy mode requires simultaneously moving 32+ coins across Binance, Upbit, and Coinbase in the exact direction needed — estimated cost: billions of dollars. SuperHeavy additionally hides the target coins until optimization runs.

---

## License

MIT
