{"id":50729070,"url":"https://github.com/justaresearcher/p2pearl","last_synced_at":"2026-06-10T07:01:25.196Z","repository":{"id":363188169,"uuid":"1262261647","full_name":"JustAResearcher/P2Pearl","owner":"JustAResearcher","description":"A decentralized, zero-fee P2Pool-style mining pool for Pearl (Pearlhash proof-of-useful-work). Feature-complete and unit-tested (73 tests); testnet bring-up in progress.","archived":false,"fork":false,"pushed_at":"2026-06-07T19:41:47.000Z","size":85,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-07T21:19:52.302Z","etag":null,"topics":["cryptocurrency","mining-pool","monero-p2pool","p2pool","pearlhash","proof-of-useful-work"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JustAResearcher.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-07T19:22:27.000Z","updated_at":"2026-06-07T19:41:50.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/JustAResearcher/P2Pearl","commit_stats":null,"previous_names":["justaresearcher/p2pearl"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/JustAResearcher/P2Pearl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JustAResearcher%2FP2Pearl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JustAResearcher%2FP2Pearl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JustAResearcher%2FP2Pearl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JustAResearcher%2FP2Pearl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JustAResearcher","download_url":"https://codeload.github.com/JustAResearcher/P2Pearl/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JustAResearcher%2FP2Pearl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34140776,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-10T02:00:07.152Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cryptocurrency","mining-pool","monero-p2pool","p2pool","pearlhash","proof-of-useful-work"],"created_at":"2026-06-10T07:00:34.670Z","updated_at":"2026-06-10T07:01:25.187Z","avatar_url":"https://github.com/JustAResearcher.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# P2Pearl\n\n**Mine [Pearl](https://github.com/pearl-research-labs/pearl) together. Keep 100 %.**\n\nP2Pearl is a mining pool with **no company behind it**: no operator, no account, no signup, and a **0 % fee**. When the pool finds a block, the block itself pays every recent miner their share, straight to their own wallet. There is nobody to take a cut, run off with funds, or get shut down — the same idea as Monero's P2Pool, built for Pearl.\n\n[![release](https://img.shields.io/github/v/release/JustAResearcher/P2Pearl)](https://github.com/JustAResearcher/P2Pearl/releases/latest) [![license](https://img.shields.io/badge/license-MIT-green)](LICENSE) ![tests](https://img.shields.io/badge/tests-109%20passing-brightgreen)\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"docs/img/gui.png\" alt=\"The P2Pearl control panel\" width=\"640\"\u003e\u003c/p\u003e\n\n## Get started in 2 minutes\n\n1. **Download** the latest release: [`p2pearl.exe`](https://github.com/JustAResearcher/P2Pearl/releases/latest) (Windows) or `p2pearl-linux-x86_64` (Linux).\n2. **Double-click it.** The control panel above opens. *(Linux: `chmod +x p2pearl-linux-x86_64 \u0026\u0026 ./p2pearl-linux-x86_64 gui`)*\n3. Pick your path:\n   - 👀 **Just curious?** Click **Run demo (no setup)** and watch two pool nodes find shares, gossip, and split a reward — live, on your machine, nothing to configure.\n   - ⛏️ **Have a GPU? Mine.** [Two steps below.](#i-want-to-mine)\n   - 🏗️ **Want to host a pool node?** [See below.](#i-want-to-run-a-pool-node)\n\nYour settings are saved automatically, so every launch after the first is open-and-click.\n\n## I want to mine\n\nYou don't install anything from P2Pearl — your existing miner just points at a P2Pearl node instead of a normal pool:\n\n1. Get [SRBMiner-Multi](https://github.com/doktor83/SRBMiner-Multi/releases) (the standard Pearlhash miner).\n2. Run it with a P2Pearl node's address and **your own wallet**:\n\n   ```\n   SRBMiner-MULTI --algorithm pearlhash --pool \u003cnode-address\u003e:3360 --wallet \u003cyour-prl1p...-address\u003e --disable-cpu\n   ```\n\nThat's it. There is no account and no balance page: **when the pool finds a block, the block's own coinbase pays you directly**, proportional to the shares you contributed recently. Nothing to claim, nothing to withdraw, no fee taken. (Rewards smaller than 0.001 PRL roll over to the next block — never lost.)\n\n\u003e Tip: anyone running the control panel can hand you the exact command — it's the **\"Miners run:\"** line at the bottom of the window, with their port and your placeholder pre-filled.\n\n## I want to run a pool node\n\nA pool node is the thing miners point at. You can run one for yourself, your friends, or the whole network — it pays you nothing extra (that's the point: 0 % fee), but it makes the pool exist.\n\n- **Windows — one exe, nothing else.** `p2pearl.exe` contains the entire stack, *including the Pearl full node itself*. Double-click it, leave **\"Run pearld for me\"** ticked, click **▶ Start node** — it unpacks `pearld` to `~/.p2pearl/bin`, starts it, shows the sync progress live, and launches the pool automatically the moment the chain is ready. Validated end-to-end on a single Windows machine (blocks built, mined, and ZK-proved on Windows, accepted by a native-Windows `pearld`).\n- **Linux** — you run your own `pearld`, plus a one-time ~15-minute build of Pearl's proof verifier: the copy-paste walkthrough is [`docs/running-a-node.md`](docs/running-a-node.md).\n\nThe control panel flow (double-click the exe, or `p2pearl gui`):\n\n1. **\"Run pearld for me\"** (Windows, on by default): pick mainnet or testnet and skip to step 3. Running your own `pearld` instead? Untick it and fill in **RPC URL / user / password**.\n2. Click **Test pearld** — it tells you if the connection works.\n3. (Optional) Add **Peers** — other operators' addresses, one per line. This merges you into one big shared pool; leave empty to run your own private pool.\n4. Click **▶ Start node.** The live log streams in the window (with sync progress if pearld is managed). Copy the **\"Miners run:\"** command to your miners. Closing the window shuts everything down cleanly.\n\nPrefer a terminal or a server? The same thing as one command: `p2pearl daemon --rpc-url ... --peer ...` — every flag is documented in the [configuration reference](#configuration-reference) below, including ready-made systemd units.\n\n## FAQ\n\n**Is there really no fee?** Really. The reward-splitting rule is enforced by every node in the pool — a coinbase that pays anyone an \"operator cut\" is rejected by consensus. There is no donation address, no dev tax, nothing.\n\n**Where does my money go?** Into the Pearl block itself, addressed directly to your wallet. Look at any block the pool mines: one output per recent miner. No middleman ever holds funds.\n\n**Do I have to trust the node I mine on?** Much less than a normal pool. Payouts are computed deterministically from the shared sharechain and cross-checked by every peer — an operator can't skim or reroute them. (Like any pool, the node you point at could ignore your shares — if you don't like a node, point at another or run your own.)\n\n**Do I need to keep P2Pearl open to mine?** No. Only the node operator runs P2Pearl; miners just run their miner.\n\n**What does the demo do? Is it safe?** It simulates a two-node pool entirely on your machine — no network, no wallet, no real coins. It's there so you can see how everything fits together.\n\n**Mainnet or testnet?** The software has mined real, confirmed blocks on Pearl's **public testnet**, including blocks paying two independent operators' miners in one coinbase. Treat mainnet as early: the remaining hardening items are listed in [Status](#status--how-to-test).\n\n**Where are my settings?** `~/.p2pearl/gui.json` (shown in the log pane). Delete it to reset.\n\n**The window closed instantly / something else is wrong?** See [Troubleshooting](#troubleshooting).\n\n---\n\n# For operators \u0026 developers\n\nEverything below is reference material — you don't need it to use P2Pearl.\n\n## Configuration reference\n\n**The easy way is the GUI** (`p2pearl gui`): it covers every setting below (rare ones behind the *Advanced* toggle), persists them to `~/.p2pearl/gui.json`, tests your pearld connection, and starts/stops the daemon with a live log. It is a thin wrapper — it launches `p2pearl daemon` with exactly the flags documented here. The release `p2pearl.exe` bundles the native proof stack, so a Windows node is download-and-run; a *source* install needs the `pearl_mining` build from [`docs/running-a-node.md`](docs/running-a-node.md) (without it, Start tells you exactly what's missing, and the demo runs anywhere).\n\nFor the daemon itself there is **no config file** — it is configured entirely by command-line flags and a few environment variables; the *sidechain consensus* lives in code (`src/p2pearl/config.py`) and must be identical on every node.\n\n### `p2pearl daemon` flags\n\n| Flag | Default | What it does / when to change it |\n|---|---|---|\n| `--rpc-url` | `http://127.0.0.1:44107` | Your `pearld` JSON-RPC endpoint. `44107` is the mainnet convention; this guide uses `44109` for testnet. Must match `pearld`'s `--rpclisten`. |\n| `--rpc-user` | `user` | `pearld` RPC username (must match `--rpcuser`). Prefer the env var below for secrets. |\n| `--rpc-pass` | `pass` | `pearld` RPC password (must match `--rpcpass`). Prefer the env var below. |\n| `--stratum-host` | `0.0.0.0` | Bind address for the miner-facing stratum listener. Use `127.0.0.1` to accept only local miners. |\n| `--stratum-port` | `3360` | The port miners point `--pool` at. |\n| `--p2p-host` | `0.0.0.0` | Bind address for the share-gossip listener. |\n| `--p2p-port` | `37900` | The port other operators `--peer` to. |\n| `--peer HOST:PORT` | *(none)* | Another operator's P2P endpoint. **Repeatable.** With no peers you run a solo pool (still feeless, still PPLNS across your own miners). Peering merges everyone into ONE pool: shares gossip both ways, every node trustlessly re-verifies them, and any node's block pays the whole network's window. New nodes window-sync the recent sharechain automatically on connect. |\n| `--share-target INT\\|HEX` | built-in | **Consensus — leave it alone** unless you are bootstrapping a brand-new private sidechain. Overrides only the GENESIS bootstrap target (`0x…` hex or decimal); after genesis the target retargets automatically. Every node on the same sidechain must use the same value or they will reject each other's shares. |\n| `--pause-cmd CMD` | *(none)* | Shell command run just before the (rare, CPU-heavy) block-prove — e.g. `'pkill -STOP -x xmrig'` to pause a co-located CPU miner. Cuts prove time ~3× on a busy box. Bounded by a 10 s timeout; failures never block a found block. |\n| `--resume-cmd CMD` | *(none)* | Undoes `--pause-cmd` right after the prove — e.g. `'pkill -CONT -x xmrig'`. Also run once at startup to self-heal a crash that died mid-prove. |\n\n### Environment variables\n\n| Variable | Default | Purpose |\n|---|---|---|\n| `P2PEARL_RPC_USER` / `P2PEARL_RPC_PASS` | — | RPC credentials, instead of putting them on the command line (visible in `ps`). Flags win if both are set. |\n| `RAYON_NUM_THREADS` | auto (= logical CPUs) | Thread count of the Rust ZK prover. The daemon pins this automatically — leaving it unset upstream makes a found-block prove ~2× slower under load. Export it yourself only to *reduce* threads. |\n| `_RJEM_MALLOC_CONF` | `background_thread:true` | jemalloc tuning for the prover (set automatically). Do **not** set `dirty_decay_ms:-1` on a memory-constrained box — it OOMs. |\n| `PYTHONPATH` | — | Must include `pearl/miner/pearl-gateway/src` (for block/ZK-certificate serialization; pure Python, no torch). Source installs only — the test suite and demo don't need it. |\n\n### Ports at a glance\n\n| Port | Protocol | Direction | Forward through your router? |\n|---|---|---|---|\n| `3360` | stratum (TCP) | miners → your node | Only if miners outside your LAN should reach you |\n| `37900` | P2P gossip (TCP) | other operators ↔ you | Yes, if you want inbound peers (outbound `--peer` works without it) |\n| `44107` / `44109` | pearld JSON-RPC | daemon → pearld, localhost | **Never** expose this publicly |\n| `44060` / `44110` | pearld chain P2P | pearld ↔ Pearl network | Recommended for a well-connected full node |\n\n### `pearld` settings that matter to P2Pearl\n\nA known-good `~/.pearld/pearld.conf` for a pool node (testnet):\n\n```ini\ntestnet=1          ; drop for mainnet\nnotls=1            ; or configure TLS and use https:// in --rpc-url\nrpcuser=u\nrpcpass=p\nrpclisten=127.0.0.1:44109\n```\n\nThe daemon polls `getblocktemplate` every ~2 s and calls `submitblock`; no wallet, indexes, or special flags are required in `pearld`. The daemon fails fast at startup if it can't reach the RPC (check URL/credentials first — see Troubleshooting).\n\n### Sidechain consensus parameters (`src/p2pearl/config.py`)\n\nThese define the sidechain itself. **Every node on a sidechain must agree on all of them — changing any one forks you off the pool.** They are deliberately not flags.\n\n| Constant | Value | Meaning |\n|---|---|---|\n| `SIDECHAIN_VERSION` | `3` | Share format/rules version. v3 = consensus retarget + subsidy-exact coinbase. v2 shares are rejected (and vice versa), so all peered nodes must run the same major version. |\n| `SHARE_TARGET_TIME_SECONDS` | `10` | The retarget aims for one share per 10 s **pool-wide**. |\n| `RETARGET_WINDOW_SHARES` | `60` | Work-rate look-back for the retarget (~10 min of shares). |\n| `RETARGET_CLAMP` | `4` | A share's target may move at most 4× per share, either direction (damps oscillation and timestamp games). |\n| `BOOTSTRAP_SHARE_TARGET` | difficulty 64 | The genesis share target; the retarget takes over from share #2. Override per-deployment with `--share-target` (consensus!). |\n| `MAX_TIMESTAMP_DRIFT_SECONDS` | `300` | Shares stamped \u003e5 min into the future are rejected (protects the retarget). |\n| `PPLNS_WINDOW_SHARES` | `1000` | The coinbase pays the miners of the last N shares, proportional to share difficulty (~2.8 h of shares at target rate). |\n| `UNCLE_BLOCK_DEPTH` / `UNCLE_PENALTY_PERCENT` | `3` / `20` | Orphaned-but-recent shares still count: full weight for chain selection, 80 % weight for payout. |\n| `MIN_PAYOUT_GRAINS` | `100000` (0.001 PRL) | Below this, a miner is skipped *this* block; their shares stay in-window for the next one. |\n\nTwo consensus rules worth knowing as an operator:\n\n- **Share targets are not negotiable.** Every share must carry exactly the target the sharechain derives for its position (`Sharechain.expected_target`). Your node computes it, stamps it into jobs, and rejects any gossiped share that disagrees — so no peer can manufacture cheap weight or flood the chain.\n- **Coinbase values are subsidy-exact.** Shares are coinbase-only (no mempool transactions yet), and every share's `coinbase_value` must equal Pearl's emission schedule for its height — replicated from `pearld`'s `CalcBlockSubsidy` and validated grain-for-grain against a live node. A finder cannot inflate the pot, and your blocks can never overpay (which `pearld` would reject).\n\n### Running as a service (systemd)\n\n```ini\n# /etc/systemd/system/pearld.service\n[Unit]\nDescription=Pearl full node\nAfter=network-online.target\n[Service]\nExecStart=/opt/pearl/bin/pearld --configfile=/root/.pearld/pearld.conf\nRestart=always\n[Install]\nWantedBy=multi-user.target\n\n# /etc/systemd/system/p2pearl.service\n[Unit]\nDescription=P2Pearl pool node\nAfter=pearld.service\nRequires=pearld.service\n[Service]\nEnvironment=PYTHONPATH=/opt/pearl/miner/pearl-gateway/src\nEnvironment=P2PEARL_RPC_USER=u\nEnvironment=P2PEARL_RPC_PASS=p\nExecStart=/opt/venv/bin/p2pearl daemon --rpc-url http://127.0.0.1:44109 \\\n    --peer \u003cother-operator\u003e:37900\nRestart=always\n[Install]\nWantedBy=multi-user.target\n```\n\n`systemctl enable --now pearld p2pearl` and both survive reboots. (The public testnet node runs exactly this shape.)\n\n### Prover speed (don't lose found blocks)\n\nThe only latency between *finding* a block and *announcing* it is generating its ZK certificate (~3–17 s of pure CPU). The daemon already pins prover threads, proves in a worker thread, serializes and dedups proves; your two knobs are `--pause-cmd`/`--resume-cmd` (pause co-located CPU load → ~3× faster prove) and **collaborative submission**, which is automatic: every peered node races to prove-and-submit any block-clearing share the moment it arrives, so the pool's orphan exposure is the *fastest* node's prove time, not each finder's. Full measurements in [`docs/running-a-node.md`](docs/running-a-node.md#prover-speed--avoiding-orphaned-blocks).\n\n### Troubleshooting\n\n| Symptom | Cause / fix |\n|---|---|\n| `could not reach pearld at …` on startup | Wrong `--rpc-url`/credentials, or `pearld` still syncing. The GUI's **Test pearld** button checks exactly this. |\n| Miner connects but never gets a job | The daemon primes its first job from `getblocktemplate` — if `pearld` is mid-sync, GBT errors until it reaches the tip. Wait for sync. |\n| Shares rejected: `share does not meet target` | Normal occasionally (the miner raced a retarget/job refresh). Constant rejections → miner is on the wrong algorithm or a stale connection; restart the miner. |\n| Gossiped shares rejected: `bad share target` / `bad coinbase value` | The peer is on different consensus (old version, or a different `--share-target` bootstrap). All nodes must run the same `SIDECHAIN_VERSION` and genesis target. |\n| Peer connect fails | Their `37900` isn't reachable (port-forward/firewall), or version mismatch. Outbound `--peer` needs no forwarding on *your* side. |\n| Block found but not on-chain | Likely orphaned — another miner found the height first while proving. Keep the prover fast (`--pause-cmd`, peers for collaborative submit). |\n| No window opens on Linux | Headless session (SSH) — the binary says so and points you at `p2pearl daemon`. The GUI needs a desktop. |\n\n## How it works (and why Pearl is a clean target)\n\nPearl is a **btcd/Bitcoin fork** (UTXO chain, `getblocktemplate`, real Bitcoin coinbase, transaction merkle root, `nbits` compact targets) with the Pearlhash proof-of-useful-work bolted on as a **succinct, CPU-verifiable ZK certificate**. That combination is almost ideal for a P2Pool port:\n\n- **One solution clears two targets.** Pearl's PoW is a plain threshold, `U256(hash_jackpot) \u003c= bound(nbits)`, and the hash is independent of the target — so the *same* solution is graded against an easy **share** target and the hard **block** target (share and block targets are nested). The Pearlhash stratum job already carries a share `target` distinct from the header's block `nbits`.\n- **The coinbase carries the commitment.** P2Pearl writes its sidechain commitment into an `OP_RETURN` output and splits the reward across many `OP_1`/P2TR miner outputs — both consensus-legal in Pearl (`P2TR` / `P2MR` / `OP_RETURN` only).\n- **Shares verify cheaply.** A peer validates an incoming share with `verify_plain_proof` (CPU, no GEMM recompute) or the ~60 KB recursive-plonky2 ZK certificate (~ms, size-independent), and every proof is cryptographically bound to its exact coinbase/payout set (no replay).\n\nThe one genuinely Pearl-specific constraint is **share/proof size on the wire** (60 KB–370 KB per share vs. a few hundred bytes in BTC/XMR P2Pool); the network design is shaped around it (per-pool difficulty caps gossip to ~1 share / share-time globally; prune to the PPLNS window; fetch proofs on demand).\n\n```\n           +---------------------------------------------------------+\n           |  p2pearl  (one daemon per miner/node)                   |\n  pearld \u003c-|  - node RPC: getblocktemplate / submitblock             |\n  (:44107) |  - coinbase builder: PPLNS P2TR outputs + OP_RETURN     |\n           |  - sidechain engine: shares, PPLNS, uncles, retarget    |\n  submit -\u003e|  - share verifier: pearl_mining.verify_plain_proof      |\n  block    |  - P2P gossip (shares + found blocks)                   |\n           |  - stratum server (dialect-tolerant; SRBMiner-ready)    |\n           +----------------^----------------------------------------+\n                            | stratum: notify{header, share_target} / submit plain_proof\n                  SRBMiner / GPU fleet (unchanged - just repoint --pool)\n```\n\n\u003e **Decentralization:** nodes form one shared pool by **gossiping shares over P2P** (`--peer`). Each incoming share is **trustlessly verified** — a peer recomputes the deterministic PPLNS payouts from its *own* sharechain, confirms the share commits to exactly that set, reconstructs the byte-identical header, verifies the proof at the consensus share target, and checks the coinbase value against Pearl's emission schedule. A finder can forge neither the PoW, the reward split, the difficulty, nor the pot size. Validated end-to-end on the public testnet with independent operators.\n\n**Why Python?** The entire reusable surface from the Pearl repo is Python: the gateway's `getblocktemplate` -\u003e coinbase -\u003e `submitblock` path, the `pearl-stratum-srv` stratum server + PPLNS split, and the `pearl_mining` (PyO3) verification bindings. The original Bitcoin P2Pool was also Python. Share throughput is low (~1 share / 10 s globally), so Python is fine for the sidechain/P2P layer; the perf-critical proof verification already lives in compiled Rust behind `pearl_mining`. See [`docs/blueprint.md`](docs/blueprint.md) for the full, source-grounded design.\n\n## Repository layout\n\n```\nsrc/p2pearl/\n  config.py              consensus params + runtime config (the sidechain \"chainparams\")\n  consensus/\n    share.py             ShareBlock: sidechain block format + serialization + id\n    pplns.py             feeless, operator-less PPLNS reward split\n    difficulty.py        difficulty \u003c-\u003e target, consensus retarget, target_to_bits\n    subsidy.py           Pearl's emission schedule, replicated exactly from pearld\n    sharechain.py        store / validate / GHOST uncles / chain-select / retarget / prune\n  chain/\n    node_rpc.py          minimal pearld JSON-RPC client (getblocktemplate/submit)\n    coinbase.py          multi-output coinbase: PPLNS P2TR outputs + OP_RETURN\n  pow/\n    verify.py            pearl_mining wrappers (nested target + nbits-override)\n  stratum/\n    protocol.py          JSON-RPC framing + Pearlhash dialect parsing\n    server.py            dialect-tolerant miner-facing stratum server\n  p2p/node.py            gossip: announce/on-demand proof fetch, relay, window sync\n  gui.py                 the tkinter control panel (settings + start/stop + live log)\n  daemon.py              PoolNode orchestrator: per-miner jobs, verify, block path\ntests/                   unit tests (109 passing)\ndocs/                    blueprint + running-a-node guide\ntools/apply_m2_binding.py  one-step additive patch for a stock Pearl checkout\nintegration/             cross-repo notes (py-pearl-mining binding, stratum dialect)\n```\n\n## Status \u0026 how to test\n\nRuns today — no node, no GPU, no native build:\n\n```bash\npip install -e \".[dev]\"\nPYTHONPATH=src python -m pytest -q       # 109 passing (pure stdlib + a faked pearl_mining)\npython -m p2pearl demo                   # watch the full pipeline: 2 nodes, stratum, P2P gossip, PPLNS\n```\n\nLive validation so far: real blocks mined and accepted on regtest **and the public Pearl testnet**, GPU miners (SRBMiner) connecting with zero protocol changes, two independent operators cross-verifying shares and sharing feeless coinbases on-chain. **Testers and contributors with a Pearl node and/or a GPU rig are very welcome** — see [issue #1](https://github.com/JustAResearcher/P2Pearl/issues/1).\n\nToward mainnet: per-miner vardiff, transaction-fee collection (shares are coinbase-only today), and a longer multi-operator testnet soak.\n\n## Development\n\n```bash\n# from the repo root\npython -m venv .venv \u0026\u0026 . .venv/Scripts/activate      # Windows; use bin/activate on *nix\npip install -e \".[dev]\"\n\n# run the full unit-test suite (pure stdlib + a faked pearl_mining; no node or GPU needed)\nPYTHONPATH=src python -m pytest -q\n```\n\nA live deployment additionally needs a running `pearld`, the Pearl repo's `pearl_mining` module\n(built via `maturin develop` on a Linux rig) and `bitcoinutils`; see [`docs/running-a-node.md`](docs/running-a-node.md).\n\n## Relationship to the Pearl repo\n\nP2Pearl depends on, but does not vendor, the Pearl repo (`pearl_mining` for proof verification; the gateway's block/coinbase serialization conventions). It anchors its sidechain to a `pearld` full node you run yourself. The M2 share-verification binding is an additive change to the Pearl repo's `zk-pow` + `py-pearl-mining`, applied by [`tools/apply_m2_binding.py`](tools/apply_m2_binding.py) and documented in [`integration/py-pearl-mining-nbits-override.md`](integration/py-pearl-mining-nbits-override.md). Consensus rules referenced throughout are grounded in `pearl/node/blockchain/validate.go` and `pearl/node/chaincfg/params.go`.\n\n## License\n\nMIT — see [`LICENSE`](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjustaresearcher%2Fp2pearl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjustaresearcher%2Fp2pearl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjustaresearcher%2Fp2pearl/lists"}