Licensing: Apache 2.0 for API/VRF; proprietary for sealed entropy core (see LICENSE).
Verifiable entropy • Post-quantum VRF • Attested boot • On-chain fairness you can prove
RE4CTOR is a sealed entropy appliance + verifiable randomness pipeline.
/randompip install r4sdk for backends/validators/botsUse cases: Casinos, sportsbooks, NFT raffles, validator rotation, ZK-rollup seeding, "prove to regulators we didn't rig this."
./run_full_demo.sh
Boots both nodes, stress-tests them, exports signed randomness, runs Solidity verification. You'll see:
If you see "6 passing", you've proven fairness locally. 🎉
Request signed randomness (ECDSA):
curl -H "X-API-Key: demo"
"http://127.0.0.1:8081/random_pq?sig=ecdsa" | jq
Expected response:
{ "random": 2689836398, "timestamp": "2025-10-28T23:46:03Z", "v": 27, "r": "0x4fe30113...", "s": "0xce79a501...", "signer_addr": "0xC61b94A8e6aDf598c8a04737192F1591cC37Db1A", "pq_mode": false }
Request Dilithium (Enterprise only):
curl -H "X-API-Key: demo"
"http://127.0.0.1:8081/random_pq?sig=dilithium" | jq
ℹ️ The public image (pipavlo/r4-local-test:latest) includes ECDSA only. The ?sig=dilithium endpoint is available in the Enterprise / FIPS-204 build, and will return:
{ "error": "Dilithium3 signature not available on this build", "pq_required": true, "status": 501, "hint": "Enterprise / FIPS 204 build required" }
pip install r4sdk
from r4sdk import R4Client
client = R4Client(api_key="demo", host="http://localhost:8080")
random_bytes = client.get_random(32)
print(f"🔐 Random: {random_bytes.hex()}")
📦 PyPI: https://pypi.org/project/r4sdk/
Returns randomness + signature proof for on-chain verification. The API supports dual-mode operation, returning both ECDSA (EIP-191) and optional post-quantum ML-DSA signatures.
curl -H "X-API-Key: demo" \
"http://localhost:8081/random_pq?sig=ecdsa" | jq
Response:
{
"random": 2689836398,
"timestamp": "2025-10-28T23:46:03Z",
"v": 27,
"r": "0x4fe30113...",
"s": "0xce79a501...",
"signer_addr": "0xC61b94A8e6aDf598c8a04737192F1591cC37Db1A",
"pq_mode": false
}
Enterprise build (?sig=dilithium) returns Dilithium3/ML-DSA (FIPS 204) signatures.
Solidity contracts under vrf-spec/contracts/:
cd vrf-spec
npx hardhat test
# → 6 passing
Demonstrates:
The sealed entropy core ships with:
R4_STRICT_FIPS=1)packages/core/proof/This package (binary, manifest, SBOM, KAT logs, test vectors) is being prepared for independent lab submission under FIPS 140-3 and post-quantum profiles (FIPS 204 / ML-DSA and FIPS 203 / ML-KEM).
Timeline:
Status: ✅ FIPS 204 Ready — All PQ signing code paths (Dilithium3) and KEM (Kyber) implemented and gated behind controlled builds.
Supply chain:
re4_release.tar.gzre4_release.sha256re4_release.tar.gz.asc (GPG)SBOM.spdx.jsonFor entropy collection, statistical tests, and reproducible FIPS/NIST validation artifacts, see the dedicated guide:
All entropy source test artifacts, manifests, and statistical reports are available under esv_artifacts/ for regulatory audit.
packages/core/proof/
| Test Suite | Result |
|---|---|
| NIST SP 800-22 | 15/15 ✅ |
| Dieharder | 31/31 ✅ |
| PractRand | 8 GB analyzed ✅ |
| TestU01 BigCrush | 160/160 ✅ |
docs/proof/benchmarks_summary.md
Every r4-fips-vrf container executes FIPS-style startup self-test before serving any entropy.
What Happens at Boot:
Integrity Check — Calculates SHA-256 of sealed entropy core (re4_dump) inside container, compares against pinned hash baked into image. If mismatch → FAIL (strict mode prevents start).
Known-Answer Test (KAT) — Runs deterministic ChaCha20 test vector to verify crypto implementation integrity. Community builds log WARN; enterprise builds enforce FAIL.
Entropy Health Tests — Pulls live random bytes directly from core before API starts:
Attestation Output — All results printed to stdout. FastAPI server starts only after PASS (or allowed PASS-with-skip).
Example Boot Log:
[r4] running FIPS startup self-test...
[INTEGRITY] OK (SHA256 match)
[KAT] ChaCha20 vector pass
[HEALTH] RNG health checks passed
FIPS STARTUP SELF-TEST: PASS
[r4] self-test passed, starting API...
INFO: Uvicorn running on http://0.0.0.0:8081
Strict-FIPS Mode (Production):
Enable fail-closed behavior for regulated environments:
docker run \
-e R4_STRICT_FIPS=1 \
-p 8081:8081 \
r4-fips-vrf:latest
| Q | Milestone | Status |
|---|---|---|
| Q1 2025 | Dilithium3 (ML-DSA / FIPS 204) signing in PQ node | ✅ Shipped |
| Q2 2025 | Kyber KEM integration for VRF key exchange | ✅ Shipped |
| Q3 2025 | Solidity verifier audit + public testnet (Sepolia) | ✅ Complete |
| Q4 2025 | Attestation + integrity self-test hardening | ✅ Complete |
| Q1 2026 | Submit module package (sealed core + SBOM + KAT logs) to lab for FIPS 140-3 / FIPS 204 review | 🚀 In progress |
| 2026 | FIPS 140-3 / FIPS 204 certification decision (lab) | ⏳ Pending lab |
Full breakdown: docs/COMPETITION.md
| Feature | R4 | Chainlink | drand | AWS HSM |
|---|---|---|---|---|
| Post-Quantum | ✅ Dilithium3 | ❌ | ❌ | ⚠️ |
| Latency | <1ms | 30-120s | 3-30s | 10-50ms |
| Cost | self-hosted | pay-per-req | free | $$$$ |
| On-chain Verify | ✅ | ✅ | ⚠️ | ❌ |
| Self-hosted | ✅ | ❌ | ✅ | ⚠️ |
| Throughput | 950k/s | limited | limited | 50k/s |
Decision: Need speed + verifiable proof? → R4. Need decentralization? → Chainlink/drand.
Solidity reference implementation for cryptographically fair lottery using RE4CTOR randomness.
Demonstrates how to:
// 1. Players register
lottery.enterLottery();
// 2. Get randomness from RE4CTOR (:8081)
// randomness, v, r, s from /random_pq?sig=ecdsa
// 3. Call drawWinner with proof
lottery.drawWinner(randomness, v, r, s);
// 4. Winner is picked deterministically
// Event: WinnerSelected(winner, index, randomness)
// 5. Regulator can verify:
// - Signature is valid (ecrecover)
// - Signer is trusted oracle
// - Winner = randomness % players.length
// - No tampering possible
function enterLottery() external {
players.push(msg.sender);
emit PlayerEntered(msg.sender);
}
Off-chain, your backend calls RE4CTOR:
curl -H "X-API-Key: secret" \
"http://localhost:8081/random_pq?sig=ecdsa" | jq
Response:
{
"random": 2689836398,
"v": 27,
"r": "0x4fe30113...",
"s": "0xce79a501...",
"signer_addr": "0xC61b94A8e6aDf598c8a04737192F1591cC37Db1A"
}
Note: API returns
randomas an integer. On-chain, we must cast it tobytes32.
function drawWinner(
bytes32 randomness,
uint8 v,
bytes32 r,
bytes32 s
) external {
// Verify signature with verifier contract
require(
verifier.verify(randomness, v, r, s, trustedSigner),
"Invalid signature"
);
// Deterministic winner selection
uint256 winnerIndex = uint256(randomness) % players.length;
address winner = players[winnerIndex];
// Emit for audit trail
emit WinnerSelected(winner, winnerIndex, randomness);
}
In JavaScript:
const randomness = Number(data.random);
const randomnessBytes32 = ethers.toBeHex(randomness, 32); // Cast to bytes32
const tx = await lottery.drawWinner(randomnessBytes32, v, r, s);
const rc = await tx.wait();
const ev = rc.logs.find(l => l.fragment?.name === 'WinnerSelected');
console.log('Winner:', ev?.args?.winner);
R4VRFVerifierCanonical.sol does:
function verify(
bytes32 randomness,
uint8 v,
bytes32 r,
bytes32 s,
address expectedSigner
) external pure returns (bool) {
// Recompute message hash
bytes32 msgHash = keccak256(abi.encodePacked(randomness));
bytes32 ethSignedHash = toEthSignedMessageHash(msgHash);
// Recover signer from signature
address recoveredSigner = ecrecover(ethSignedHash, v, r, s);
// Check it's the trusted oracle
return recoveredSigner == expectedSigner;
}
Regulator/auditor can verify:
// 1. Was signature valid?
bool isValid = verifier.verify(randomness, v, r, s, trustedSigner);
// 2. Who was the signer?
address signer = ecrecover(...); // must be RE4CTOR oracle
// 3. Was winner picked fairly?
uint256 expectedIndex = uint256(randomness) % players.length;
require(winner == players[expectedIndex]);
// 4. Could operator cheat?
// NO - signature proves randomness comes from oracle
// NO - modulo operation is deterministic
// NO - both are on-chain and immutable
Prerequisites:
Setup:
cd vrf-spec
# Install dependencies
npm ci
# Compile contracts
npx hardhat compile
# Run tests
npx hardhat test
# Expected: ✔ 6 tests passing
Test Output:
LotteryR4
✔ enters 3 players (185ms)
✔ picks deterministic winner with valid randomness (425ms)
✔ reverts if signature is invalid (218ms)
✔ emits WinnerSelected event (195ms)
R4VRFVerifier
✔ verifies valid ECDSA signature (150ms)
5 passing (1.2s)
R4VRFVerifierCanonical.sol — Core signature verification contract
contract R4VRFVerifierCanonical {
function verify(
bytes32 randomness,
uint8 v,
bytes32 r,
bytes32 s,
address signer
) external pure returns (bool);
event RandomnessVerified(
address indexed caller,
bytes32 indexed randomness
);
}
LotteryR4.sol — Reference lottery implementation
contract LotteryR4 {
address[] public players;
R4VRFVerifierCanonical public verifier;
address public trustedSigner;
function enterLottery() external;
function drawWinner(bytes32 randomness, uint8 v, bytes32 r, bytes32 s) external;
event PlayerEntered(address indexed player);
event WinnerSelected(address indexed winner, uint256 index, bytes32 randomness);
}
Run All Tests:
npx hardhat test
Test Coverage:
Manual Testing (Local):
# 1. Start local Hardhat network
npx hardhat node
# 2. In another terminal, deploy
npx hardhat run scripts/deploy.js --network localhost
# 3. Run tests against local network
npx hardhat test --network localhost
What's Proven Cryptographically:
What's NOT Proven (By Design):
vrf-spec/
├── contracts/
│ ├── R4VRFVerifierCanonical.sol (← verification core)
│ └── LotteryR4.sol (← lottery reference)
├── test/
│ ├── lottery.js (← lottery tests)
│ └── verify_r4_canonical.js (← verifier tests)
├── scripts/
│ └── deploy.js (← deployment)
├── hardhat.config.js
└── README.md
Player 1 ──┐
Player 2 ──┤ enterLottery()
Player 3 ──┘
↓
[Players stored on-chain]
↓
Backend calls RE4CTOR (:8081)
← randomness + (v,r,s)
↓
Backend calls drawWinner(randomness, v, r, s)
↓
Contract verifies signature with R4VRFVerifierCanonical
✅ Valid? Continue
❌ Invalid? Revert
↓
winnerIndex = randomness % players.length
winner = players[winnerIndex]
↓
Emit WinnerSelected(winner, index, randomness)
↓
Regulator/auditor verifies on-chain
1. Casino / Sportsbook — Players enter, game round happens, at settlement call drawWinner() with RE4CTOR signature, winner determined on-chain, regulator audits transaction history.
2. NFT Raffle — Users register for raffle, at deadline drawWinner() selects NFT winner, winner address gets transferred NFT, community verifies fairness.
3. DAO Treasury Distribution — Community members enter for allocation round, randomness selects who gets funded first, provably fair allocation, governance token holders audit.
4. Validator / Sequencer Rotation — Validators register for next epoch, randomness selects leader/sequencer, proof that selection was fair, no validator favoritism.
5. Decentralized Lottery — Players buy tickets (ETH/ERC-20), at draw time randomness picks winner, winner gets jackpot, transparent on-chain for all to verify.
Step 1: Deploy Verifier
R4VRFVerifierCanonical verifier = new R4VRFVerifierCanonical();
Step 2: Deploy Your Lottery
LotteryR4 lottery = new LotteryR4(
address(verifier),
0xC61b94A8e6aDf598c8a04737192F1591cC37Db1A
);
Step 3: Off-Chain: Get Randomness
import requests
response = requests.get(
"http://localhost:8081/random_pq?sig=ecdsa",
headers={"X-API-Key": "your-key"}
)
data = response.json()
randomness = int(data["random"])
v = data["v"]
r = int(data["r"], 16)
s = int(data["s"], 16)
Step 4: On-Chain: Call drawWinner
const randomness = Number(data.random);
const randomnessBytes32 = ethers.toBeHex(randomness, 32); // Cast to bytes32
const tx = await lottery.drawWinner(randomnessBytes32, v, r, s);
const rc = await tx.wait();
const ev = rc.logs.find(l => l.fragment?.name === 'WinnerSelected');
console.log(`Winner: ${ev?.args?.winner}`);
Step 5: Audit
const tx = await lottery.drawWinner(randomnessBytes32, v, r, s);
const rc = await tx.wait();
const ev = rc.logs.find(l => l.fragment?.name === 'WinnerSelected');
const winner = ev?.args?.winner;
const expectedIndex = BigInt(randomness) % BigInt(await lottery.playerCount());
const expectedWinner = await lottery.players(expectedIndex);
console.assert(winner === expectedWinner, 'Fairness check passed!');
Q: Can I use this in production?
A: Yes. Contracts audited and tested. Recommended: redeploy + re-audit on mainnet, use trusted RE4CTOR oracle endpoint, legal review of on-chain terms.
Q: What if signature is invalid?
A: Transaction reverts. No winner selected. Players remain registered for next round.
Q: Can players collude with operator?
A: No. Even if operator & signer collude, they can't: retroactively change winner (modulo deterministic), forge signature (ECDSA secure), reroll without on-chain record.
Q: What if RE4CTOR oracle is compromised?
A: Worst case: signature could be replayed. But: every draw is on-chain & auditable, regulator detects suspicious patterns, you can rotate to new signer/oracle.
Q: How do I integrate with my own game?
A: Copy R4VRFVerifierCanonical.sol, inherit from LotteryR4.sol, extend for your use case.
r4-monorepo/
├── README.md (← you are here)
├── CONTRIBUTING.md (how to help)
├── SPONSORS.md (enterprise)
├── run_full_demo.sh (one-command test)
├── stress_core.sh (load test :8080)
├── stress_vrf.py (load test :8081)
│
├── packages/core/
│ ├── runtime/bin/re4_dump (sealed entropy core)
│ │ (community images ship a tiny stub at docker/stubs/re4_dump for CI sanity checks)
│ ├── proof/ (Dieharder/PractRand/BigCrush results)
│ └── manifest/ (sha256, GPG sig, SBOM)
│
├── vrf-spec/
│ ├── contracts/
│ │ ├── R4VRFVerifierCanonical.sol
│ │ └── LotteryR4.sol
│ ├── test/
│ │ ├── lottery.js
│ │ ├── verify.js
│ │ └── verify_r4_canonical.js
│ ├── scripts/
│ │ └── deploy.js
│ ├── hardhat.config.js
│ └── package.json
│
├── api/
│ ├── app.py (core :8080)
│ ├── app_dual.py (PQ/VRF :8081)
│ ├── dual_router.py
│ ├── sign_ecdsa.py
│ └── sign_pq.py
│
├── sdk_py_r4/
│ ├── r4sdk/ (Python client)
│ ├── test_r4sdk.py
│ └── setup.py
│
├── tools/
│ └── verify_vrf_msg_hash.py
│
└── docs/
├── USAGE.md
├── DEPLOYMENT.md
├── COMPETITION.md
├── FIPS_204_roadmap.md
├── ESV_README.md
└── proof/benchmarks_summary.md
We accept PRs for:
See CONTRIBUTING.md for rules and disclosure policy.
Documentation:
Community:
Enterprise & Regulated Gaming:
Maintainer: Pavlo Tvardovskyi
📧 Email: [email protected]
🐙 GitHub: @pipavlo82
🐳 Docker Hub: pipavlo/r4-local-test
📦 PyPI: r4sdk
v1.0.0-demo | GitHub | PyPI | Docker Hub
Content type
Image
Digest
sha256:c48104c39…
Size
204.8 MB
Last updated
11 months ago
docker pull pipavlo/r4-local-test