Creating a TREZ Mining Pool: Developer's Guide

Creating a TREZ Mining Pool: Developer's Guide

Last updated: October 2025

This guide provides an in-depth walkthrough for developers to create a mining pool that connects to the TREZ mining contract on Solana (EUBkEwKJJnuenTnocaUHDZUaSegeWWZAFwBTqTRcQ1sJ). A mining pool allows multiple miners to combine their computational power (hashrate) to increase the chances of finding valid proof-of-work (PoW) solutions, with rewards distributed proportionally based on contributed shares. The pool server interacts with the TREZ contract to submit valid solutions via the claim_reward instruction and handles reward distribution.

The guide assumes familiarity with Python, Solana development, and the TREZ mining contract. We’ll use Python for the pool server (FastAPI + WebSockets) and provide example code for both the server and client miners. You can adapt this to other languages or frameworks.

Table of Contents

Overview of Mining Pools

In the TREZ ecosystem, individual miners solve SHA-256 challenges to meet the dynamic difficulty (targeting ~180-second blocks) and claim rewards via claim_reward. A mining pool aggregates miners’ efforts:

  • Shares: miners submit partial solutions that meet a pool-defined lower difficulty.
  • Valid Solutions: when a share meets the on-chain difficulty, the pool submits it to the contract.
  • Payouts: rewards (base block reward and any applicable referral bonus) are distributed by the pool based on contributed shares (e.g., PPLNS).
  • Benefits: reduces variance for small miners and increases collective hashrate.

The pool connects to the TREZ contract to fetch state (challenge, difficulty) and to submit claim_reward when a full-difficulty solution is found.

Prerequisites

  • Programming: Python 3.8+.
  • Solana Tools:
    • Solana CLI: sh -c "$(curl -sSfL https://release.solana.com/v1.18.20/install)"
    • Anchor: cargo install --git https://github.com/coral-xyz/anchor anchor-cli --locked
  • Python Dependencies: install via pip install -r requirements.txt
  • TREZ Contract Details:
    • Program ID: EUBkEwKJJnuenTnocaUHDZUaSegeWWZAFwBTqTRcQ1sJ
    • Mint: TREZuzaCxTVsg4U9c4MTe7dterWcLe5LA92PHG12Jez (6 decimals)
    • IDL: idl/trez.json (generate with Anchor as needed)
  • Pool Wallet: a Solana wallet for the pool operator to submit transactions and distribute rewards.
  • Server Hosting: a VPS (e.g., EC2, DigitalOcean) for running the pool server.
  • Database: SQLite or Redis for tracking shares and miner stats.

Sample requirements.txt

fastapi==0.111.0
uvicorn==0.30.1
websockets==12.0
anchorpy==0.19.0
solana==0.34.3
solders==0.21.0
redis==5.0.7  # Optional, for high-scale stats

Install:

# Linux/macOS
python3 -m pip install -r requirements.txt

# Windows PowerShell
python -m pip install -r requirements.txt

Pool Architecture

  • Pool Server:
    • Fetches on-chain state (challenge, difficulty) from the TREZ contract.
    • Assigns work to miners via WebSockets.
    • Validates submitted shares (pool difficulty vs. on-chain difficulty).
    • Submits valid solutions using the pool wallet via claim_reward.
    • Tracks shares in a database for payout calculation.
  • Miner Clients:
    • Connect to the pool via WebSocket.
    • Receive work (challenge, difficulty) and mine shares.
    • Submit shares to the pool for credit.
  • Reward Flow:
    • Pool receives TREZ rewards and distributes to miners based on shares (minus optional pool fee).

Setting Up the Pool Server

  1. Create the Project Structure:
    mkdir trez-mining-pool
    cd trez-mining-pool
    touch server.py database.py config.py
    
  2. Configure the Pool (in config.py):
    RPC_URL = "https://api.mainnet-beta.solana.com"
    PROGRAM_ID = "EUBkEwKJJnuenTnocaUHDZUaSegeWWZAFwBTqTRcQ1sJ"
    TREZ_MINT = "TREZuzaCxTVsg4U9c4MTe7dterWcLe5LA92PHG12Jez"
    POOL_WALLET_SECRET = "your_pool_wallet_secret_base58"  # Securely store this!
    POOL_DIFFICULTY = 20        # Lower than on-chain for pool shares
    SHARE_WINDOW = 1000         # N for PPLNS
    POOL_FEE = 0.01             # 1% fee (optional)
    
  3. Set Up Database (in database.py):
    import sqlite3, time
    
    def init_db():
        conn = sqlite3.connect('pool.db')
        c = conn.cursor()
        c.execute('''CREATE TABLE IF NOT EXISTS shares
                     (miner TEXT, timestamp REAL, share_count INTEGER)''')
        conn.commit()
        return conn
    
    def add_share(conn, miner: str, count: int = 1):
        c = conn.cursor()
        c.execute("INSERT INTO shares VALUES (?, ?, ?)", (miner, time.time(), count))
        conn.commit()
    
    def get_last_n_shares(conn, n: int):
        c = conn.cursor()
        c.execute("SELECT miner, SUM(share_count) FROM shares GROUP BY miner "
                  "ORDER BY MAX(timestamp) DESC LIMIT ?", (n,))
        return c.fetchall()
    

Example Pool Server Code

The FastAPI WebSocket server assigns jobs, validates shares, submits full-difficulty solutions, and accounts for payouts. Stub methods like token transfers should be implemented for production.

# server.py
import asyncio, json, time, hashlib
from fastapi import FastAPI, WebSocket
from anchorpy import Program, Provider, Wallet
from solana.rpc.async_api import AsyncClient
from solders.pubkey import Pubkey
from solders.keypair import Keypair
from config import RPC_URL, PROGRAM_ID, TREZ_MINT, POOL_WALLET_SECRET, POOL_DIFFICULTY, SHARE_WINDOW, POOL_FEE
from database import init_db, add_share, get_last_n_shares

app = FastAPI()
conn = init_db()

async def load_program():
    client = AsyncClient(RPC_URL)
    wallet = Wallet(Keypair.from_base58_string(POOL_WALLET_SECRET))
    provider = Provider(client, wallet)
    # Load IDL from file
    with open("idl/trez.json", "r") as f:
        idl = json.load(f)
    program = Program(idl, Pubkey.from_string(PROGRAM_ID), provider)
    return program, client, provider

program, client, provider = asyncio.get_event_loop().run_until_complete(load_program())

async def get_state():
    state_pda = Pubkey.find_program_address([b"state"], Pubkey.from_string(PROGRAM_ID))[0]
    state = await program.account["State"].fetch(state_pda)
    return {
        "challenge": bytes(state.challenge_number).hex(),
        "difficulty": int(state.difficulty_high),
        "block_count": int(state.block_count)
    }

def meets_difficulty(digest: bytes, difficulty: int) -> bool:
    u192 = int.from_bytes(digest[:24], "little")
    return (u192 >> (192 - difficulty)) == 0

def compute_digest(challenge: bytes, miner_pk: Pubkey, block_count: int, nonce: int) -> bytes:
    nonce_bytes = nonce.to_bytes(8, "little")
    miner_bytes = bytes(miner_pk)
    block_bytes = block_count.to_bytes(8, "little")
    return hashlib.sha256(challenge + miner_bytes + block_bytes + hashlib.sha256(nonce_bytes).digest()).digest()

@app.websocket("/mine")
async def mine_ws(ws: WebSocket):
    await ws.accept()
    # TODO: auth the miner and set miner_address
    miner_address = None
    while True:
        state = await get_state()
        challenge = bytes.fromhex(state["challenge"])
        await ws.send_json(state)

        data = await ws.receive_json()
        nonce = int(data["nonce"])
        digest = bytes.fromhex(data["digest"])

        # Pool difficulty check (share credit)
        if meets_difficulty(digest, POOL_DIFFICULTY):
            add_share(conn, miner_address or "unknown")

            # On-chain difficulty (submit claim)
            if meets_difficulty(digest, state["difficulty"]):
                # TODO: call program.methods.claim_reward(...).accounts(...).rpc()
                # TODO: on success, trigger payout distribution
                pass

        await asyncio.sleep(0.05)

async def distribute_rewards():
    shares = get_last_n_shares(conn, SHARE_WINDOW)
    total = sum(s[1] for s in shares) or 0
    if total == 0:
        return
    # TODO: read pool balance, split minus POOL_FEE, transfer to miners
    for miner, scount in shares:
        portion = scount / total
        # TODO: transfer 'portion * reward' to miner ATA (transfer_checked)
        pass

Miner Client Integration

Modify your miner to connect to the pool’s WebSocket, receive work, and submit shares back when a nonce meets the pool difficulty.

Example Miner Client Code

# miner_client.py
import asyncio, json, hashlib, random, websockets
from solders.pubkey import Pubkey

POOL_URL = "ws://your-pool-server.com/mine"
MINER_PUBKEY = Pubkey.from_string("YourMinerPubkeyHere")

def meets_difficulty(digest: bytes, difficulty: int) -> bool:
    u192 = int.from_bytes(digest[:24], "little")
    return (u192 >> (192 - difficulty)) == 0

def compute_digest(challenge: bytes, miner_pk: Pubkey, block_count: int, nonce: int) -> bytes:
    nonce_b = nonce.to_bytes(8, "little")
    miner_b = bytes(miner_pk)
    block_b = block_count.to_bytes(8, "little")
    return hashlib.sha256(challenge + miner_b + block_b + hashlib.sha256(nonce_b).digest()).digest()

async def mine_pool():
    async with websockets.connect(POOL_URL) as ws:
        while True:
            work = json.loads(await ws.recv())
            challenge = bytes.fromhex(work["challenge"])
            difficulty = int(work["difficulty"])
            block_count = int(work["block_count"])

            while True:
                nonce = random.getrandbits(64)
                digest = compute_digest(challenge, MINER_PUBKEY, block_count, nonce)
                if meets_difficulty(digest, difficulty):  # full-diff or just send all shares
                    await ws.send(json.dumps({
                        "nonce": nonce,
                        "digest": digest.hex()
                    }))
                    break  # request new work

asyncio.run(mine_pool())

Reward Distribution

  • PPLNS: use the last N shares to calculate payouts so miners are rewarded proportionally to recent contribution.
  • Implementation: after a successful claim_reward, sum shares in the window and perform transfer_checked to miners’ ATAs.
  • Pool Fee: deduct an optional operator fee before distribution.

Security Considerations

  • Authentication: sign a nonce with miners’ wallets or use API keys tied to addresses.
  • Share Validation: verify digests server-side; don’t trust client difficulty checks.
  • Rate Limiting: throttle connections and messages to mitigate spam/DoS.
  • Key Management: protect the pool wallet (consider HSM/airgapped signing for production).
  • Monitoring: log submissions, accepts/rejects, and payouts for auditability.

Testing and Deployment

  • Local: run the server with uvicorn server:app --reload and connect test miners.
  • Deployment: host behind Nginx with TLS; consider Docker for portability.
  • Observability: export metrics (Prometheus) and alerts for hashrate, latency, and error spikes.

Scaling and Optimization

  • Redis for real-time share counters and leaderboards.
  • Worker Threads/Processes for hash validation and DB writes.
  • Dynamic Pool Difficulty to keep share rates stable as hashrate grows.
  • Stratum-like Protocol if you need industry-standard miner compatibility.

Resources


This guide is for developers. Operating a pool involves security, compliance, and operational risks—review and audit your implementation before going live.