ParitrDocs
Everything about how the network works, how to install your own node on Linux or Windows, and how to connect it to your wallet.
What is Paritr?
Paritr is an independent cryptocurrency along the lines of Bitcoin. The network has two parts:
- Full nodes – independent servers that store the entire blockchain, check every rule, relay transactions and create new blocks through proof of work. Anyone can run one.
- Web platform – your wallet in the browser. The private key is generated locally and never leaves your browser. The platform talks to a node in the background to read balances and submit signed transactions.
How the blockchain works
Blocks and proof of work
Every block carries an 80 byte header made of the version, the hash of its predecessor, the Merkle root of all transactions, a timestamp, the difficulty (nBits) and a counter (nonce). A block is identified by SHA256(SHA256(header)). The proof of work, however, uses scrypt with 2 MiB of memory per hash (N = 2048, r = 8, p = 1). A block is valid once that scrypt hash is less than or equal to the target. Miners vary the nonce until it is.
The memory requirement is deliberate. Plain SHA256d can be accelerated a millionfold by off-the-shelf special-purpose hardware (ASICs) that already exists for Bitcoin. A fraction of it would raise the difficulty here so far that ordinary computers would stand no chance. scrypt makes memory latency the bottleneck instead of raw arithmetic – the same approach that kept ASICs away from CryptoNight for years.
Account model
Instead of UTXOs, Paritr uses an account/nonce model: every address has a balance and a running counter. Each transaction carries the sender’s next nonce – duplicate or skipped nonces are rejected. That prevents replay and keeps wallets very light.
Over the network, though, transactions from the same sender do not necessarily arrive in order. If nonce n+1 shows up before n, it is not discarded but buffered briefly and applied automatically once the gap closes.
Signatures and addresses
Signing uses ECDSA on the secp256k1 curve. An address is Base58Check(0x37 ‖ RIPEMD160(SHA256(pubkey))) and therefore always starts with P. The node checks that the sender address matches the public key supplied with the transaction.
Consensus and reorganisation
Nodes do not compare the length of a chain but the total work put into it. A foreign chain is only adopted if it contains more work and every single block satisfies all rules. During a reorganisation, transactions from orphaned blocks move back into the queue (mempool) and shares back into the share store.
Only the differing part is rebuilt: blocks from the fork point onwards are rolled back, then exclusively the new branch is verified and applied. The cost therefore depends on the depth of the reorganisation, not on the length of the whole chain.
A delivered block that does not attach to the local tip is not thrown away but kept as a side branch. As soon as enough successors arrive and the branch carries more work, the node switches over. Without that step a node unable to open outbound connections could sit on its own fork forever – losing the other side’s blocks and rewards.
State roots and snapshots
Replaying the entire history is fine for a young chain and painful for an old one. Paritr therefore commits a state root – a Merkle root over every account balance and nonce – every 720 blocks (about twelve hours). Because the root is part of the block, a new node can verify a downloaded state snapshot against the chain instead of replaying millions of blocks.
Each node keeps the two most recent snapshots on disk and offers them at /state/snapshot. Computing the root only every 720th block keeps the per-block cost at exactly zero for the other 719.
How nodes find each other
- Seed nodes hard-coded in the program.
- DNS seeds: resolved addresses are used as candidates – but only for hosts that are not already known as a seed URL. Otherwise dead entries appear, because behind a reverse proxy or CDN the A records point at edge addresses where the RPC port is not open.
- Gossip: nodes exchange their peer lists during the handshake.
- Return path: if a peer reports no public address, a candidate is formed from its source IP plus the RPC port it announced, and then probed.
- Deduplication: if the same node is known under several addresses (seed URL, port variant, resolved IP), only the best one is used and gossiped.
- Headers-first sync: verify all headers, then download the blocks.
- The genesis block is computed deterministically and identically on every node.
Three kinds of message travel over those same connections: blocks, transactions and shares. All outbound calls are handled by a fixed number of background workers, so a slow or malicious peer can neither stall the node nor exhaust it with unlimited connections.
Wire format
Shares and blocks are also offered in a compact binary framing at /p2p/share/bin and /p2p/block/bin (magic PSH1 / PBK1, 4 MiB message ceiling). That roughly halves the relay traffic compared to JSON. Nodes negotiate the format automatically and fall back to JSON when a peer does not support it.
Emission and tail emission
Every new block creates fresh coins – the subsidy. It starts at 10 PAR and halves every 1,600,000 blocks, roughly every three years.
Why no cap?
A network with a hard cap eventually funds its security purely from transaction fees. If those dry up, computing power falls – and with it the protection against attacks. Tail emission solves that: it guarantees a predictable minimum reward without letting the money supply run away.
What matters is not the absolute amount but the annual inflation rate. Because the circulating supply grows while the yearly issuance stays constant, that rate falls towards zero forever without ever reaching it. The /supply endpoint shows the current value.
| Period (approx.) | Blocks | Reward per block |
|---|---|---|
| Year 1–3 | 1 – 1,600,000 | 10 PAR |
| Year 4–6 | 1,600,001 – 3,200,000 | 5 PAR |
| Year 7–9 | 3,200,001 – 4,800,000 | 2.5 PAR |
| … | … | … |
| from ~year 13 | permanently | 0.5 PAR (tail emission) |
Mining and rewards
The cycle
- Submitted transactions collect in the mempool, incoming shares in the node’s share store.
- The node builds a candidate block: first the shares to be confirmed, from those the distribution key and the coinbase outputs, then the transactions with the highest fees.
- The nonce is varied until the header hash falls below the target. Intermediate hits below the easier share target are published as shares.
- The finder appends the block and relays it to all known peers.
If no transaction is pending, an empty block with only the coinbase outputs is produced. The network therefore keeps working without interruption.
Who gets what?
| Share | Recipient | Purpose |
|---|---|---|
| 95 % of the subsidy | every miner with shares in the measuring window | strictly proportional: pool × own shares / all shares |
| 5 % of the subsidy | the node that found the block | incentive to include foreign shares instead of censoring them |
| 100 % of the fees | the node that found the block | incentive to build full blocks and drain the mempool |
There are at most 32 recipients per block; slices below 0.00001 PAR and rounding remainders go to the finder. The sum of all outputs therefore equals exactly subsidy plus fees – every node recomputes that in pure integer arithmetic. The aggregated figures are shown under Mining › Network overview and by the /mining/distribution endpoint.
Maturity
Freshly mined coins are locked at first and only spendable after 10 further blocks. Until then the overview shows Pending, afterwards Confirmed. That protects against reversals if the chain reorganises briefly.
Consensus parameters
These values are fixed in the protocol and identical on every node. They can be changed neither through the configuration nor through the web interface.
| Chain id | paritr-mainnet |
| Smallest unit | 0.00000001 PAR (1 coin = 100,000,000 units) |
| Initial reward | 10 PAR per block |
| Halving | every 1,600,000 blocks (~3 years) |
| Minimum reward | 0.5 PAR per block (tail emission) |
| Maximum supply | no fixed cap – see emission |
| Target block time | 60 seconds |
| Proof of work | scrypt (N = 2048, r = 8, p = 1) – 2 MiB per hash |
| Difficulty retarget | every 60 blocks (~1 h), damped to factor 4 |
| Reward maturity | 10 blocks |
| Reward split | 95 % by share of work, 5 % + all fees to the finder |
| Measuring window | 120 blocks (~2 hours) |
| Share difficulty | 1/100 of the block difficulty |
| Shares per block | max. 32 |
| Coinbase recipients per block | max. 32 |
| State checkpoint | every 720 blocks (~12 h) |
| Minimum fee | 0.001 PAR |
| Minimum amount | 0.00001 PAR |
| Block size | max. 500 transactions |
| Address format | Base58Check, prefix P |
Install a node
A Paritr node runs anywhere Python 3.9 or newer is available. Tested platforms:
| System | Architecture | Installation |
|---|---|---|
| Ubuntu 20.04+ / Debian 11+ | x86_64 | install.sh |
| Ubuntu / Debian / Raspberry Pi OS | aarch64, armv7l | install.sh |
| Windows 10 / 11 / Server 2019+ | x64, ARM64 | install.ps1 |
| macOS, other distributions | any | manual |
Minimum requirements
- Python 3.9 or newer
- 2 GB RAM, 2 GB free disk space (grows with the chain)
- A permanent internet connection
- A reachable TCP port (default 5050) – recommended, but not required
All files at a glance
The installers download everything else themselves – you only need the individual files for a manual setup.
Linux: Ubuntu, Debian and ARM
The script behaves identically on x86_64 servers and on ARM devices (Raspberry Pi 4/5, Oracle Ampere, AWS Graviton, …). The architecture is detected automatically.
One command sets up the Python environment, the service and the firewall.
curl -fsSL https://paritr.highactive.de/dist/install.sh -o install.sh
bash install.sh --source https://paritr.highactive.de/dist
bash install.sh \
--address P… # payout address of your wallet
--port 5050 # RPC port
--public-url https://node1.example.org
--cores 2 # worker processes (0 = automatic)
--intensity 60 # load per process in percent
--cpu-quota 150% # hard CPU limit (150 % = 1.5 cores)
Without arguments the script asks for the wallet address interactively and uses sensible defaults for everything else. The public address is detected automatically if you do not pass --public-url.
- Installs Python, venv and build tools (needed on ARM)
- Creates ~/paritr-node with its own Python environment
- Downloads node.py, wsgi.py and manage.sh into that directory
- Generates config.json including a fresh admin secret key
- Sets up the systemd service paritr-node (autostart, restart on failure, throttled CPU priority)
- Opens the port in ufw or firewalld
The admin secret key is printed at the end of the installation. You need it to connect the node in your wallet. You can read it again at any time:
cd ~/paritr-node && ./manage.sh secret
Windows
On Windows, install.ps1 handles the setup. waitress is used as the server process and autostart runs through a scheduled task.
If it is not present yet – when installing manually, be sure to tick „Add python.exe to PATH“.
winget install -e --id Python.Python.3.12
Right-click the start menu → Terminal (Administrator). Administrator rights are needed for the firewall rule and the autostart task.
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force
Invoke-WebRequest 'https://paritr.highactive.de/dist/install.ps1' -OutFile install.ps1
.\install.ps1 -Source 'https://paritr.highactive.de/dist'
.\install.ps1 `
-Address P… `# payout address
-Port 5050 `# RPC port
-Cores 2 `# worker processes (0 = automatic)
-Intensity 60 `# load per process in percent
-Dir 'D:\Paritr' `# custom directory
-NoAutostart # without a scheduled task
The default directory is %LOCALAPPDATA%\Paritr\node.
It is printed at the end and can be read again with:
.\manage.ps1 secret
Manual installation (macOS, other systems)
# 1. Fetch the files
mkdir paritr-node && cd paritr-node
curl -fsSL https://paritr.highactive.de/dist/node.py -o node.py
curl -fsSL https://paritr.highactive.de/dist/wsgi.py -o wsgi.py
# 2. Create the Python environment
python3 -m venv venv
./venv/bin/pip install Flask requests ecdsa waitress
# 3. Start the node (creates config.json on first run)
./venv/bin/python node.py --port 5050 --address P…
# 4. Read the admin secret key
python3 -c "import json;print(json.load(open('config.json'))['admin_secret'])"
Control hardware usage
How much power your node spends on mining is entirely up to you – conveniently through the sliders in the Mining area of the web platform, or directly on the server.
| Setting | Meaning | Values |
|---|---|---|
| Cores mining_processes | Number of parallel worker processes. Never larger than the number of available CPU cores. | 0 = automatic (all cores minus 1) |
| Intensity mining_intensity | Working share per time slice. At 50 % the node computes exactly as long as it pauses – halving power draw and heat. | 5 – 100 (%) |
| CPU quota (Linux only) | A hard ceiling enforced by systemd, independent of the node configuration. | e.g. 150% |
Through the web platform
Mining › My nodes › Settings › Performance: the two sliders show the expected total load live. Changes take effect immediately after saving – no restart needed. An admin secret key must be stored for the node.
On the server
# Linux
./manage.sh cores 2 # two worker processes
./manage.sh intensity 60 # 60 % load per process
./manage.sh cpuquota 150% # hard systemd limit
# Windows
.\manage.ps1 cores 2
.\manage.ps1 intensity 60
.\manage.ps1 priority BelowNormal
Become reachable
Your node finds the network on its own, even behind a router. For other nodes to reach it and for the web platform to talk to it directly, the port should be reachable.
- Give the server a fixed local IP address in your router.
- Set up port forwarding: 5050/TCP to that IP.
- With a changing public IP, set up a DynDNS name and pass it as --public-url during installation.
- Check reachability: curl http://YOUR-ADDRESS:5050/status
The installer detects your public address automatically and writes it to config.json. You can correct it later with ./manage.sh publicurl https://…; the node itself reports what its peers see at /p2p/whoami.
Connect a node to the wallet
Connecting is what lets you monitor and control your node in the web platform. The connection belongs to your account only.
It was shown at the end of the installation. To read it again:
./manage.sh secret # Linux
.\manage.ps1 secret # Windows
Mining › My nodes › Connect a node. Enter:
- Label – free choice, e.g. „home server“
- Address – complete including the port, e.g. http://my-node.example:5050
- Admin secret key – required
The Test button checks reachability, block height and whether the node belongs to the right chain. Then press Connect.
In the Mining area open the node settings and use My address, then save. From then on all mined coins flow straight into your wallet.
Operation and maintenance
Linux
./manage.sh status # service status and block height
./manage.sh logs # live log
./manage.sh restart # restart the service
./manage.sh secret # show the admin secret key
./manage.sh address P… # set the payout address
./manage.sh mining on|off # toggle mining
./manage.sh cores 2 # limit worker processes
./manage.sh intensity 60 # limit load
./manage.sh publicurl https://node1.example.org
./manage.sh peers # known nodes
./manage.sh addpeer http://… # add a peer manually
./manage.sh rmpeer http://… # remove a peer
./manage.sh update https://paritr.highactive.de/dist # update the software
Windows
.\manage.ps1 status
.\manage.ps1 restart
.\manage.ps1 secret
.\manage.ps1 address P…
.\manage.ps1 mining on
.\manage.ps1 cores 2
.\manage.ps1 intensity 60
.\manage.ps1 peers
.\manage.ps1 update https://paritr.highactive.de/dist
Configuration file
{
"rpc_host": "0.0.0.0",
"rpc_port": 5050,
"public_url": "https://node1.example.org",
"admin_secret": "…",
"miner_address": "P…",
"mining_enabled": true,
"mining_processes": 0,
"mining_intensity": 100,
"seed_nodes": ["https://node0.oe-net.de"],
"data_dir": "data",
"rpc_cors_origins": "*"
}
Restart the service after editing config.json by hand. Changes made through the web platform or manage take effect immediately.
Backups
The only file you need to back up is config.json (it holds the admin secret key). A new node loads the blockchain itself from the network. Your balance lives in the blockchain – not on the node.
Security
- Private key: generated in the browser and stored encrypted with your password only (AES-256-GCM). Without the key and the password there is no access to your balance – and no recovery by anyone else. Back it up under Account › Back up key.
- Admin secret key: belongs to the node, not the wallet. It permits no transfers, only control of the node.
- Node privileges: the systemd service runs without elevated rights and may only write to its own directory.
- CORS: rpc_cors_origins lets you restrict access to your own platform instead of allowing *.
- Server proxy: the platform only calls allow-listed endpoints and refuses requests into private networks (SSRF protection).
Common problems
| Symptom | Cause and fix |
|---|---|
| The platform shows the node as „unreachable“ | Check port forwarding and firewall. With an HTTPS site and an http node the server proxy takes over – the node has to be reachable from the internet for that. |
| „Invalid admin secret key“ (403) | Read the key again with manage.sh secret and re-enter it under My nodes › Settings › Connection. |
| Badge „No address“ | No payout address is set. Without one the node does not mine. |
| Every value in the platform stays at 0 | Your account still holds an address from before version 5.0.0 (starting with C). Sign in once – the platform re-derives the address from your public key automatically. Also make sure the node itself is running and its chain id is paritr-mainnet. |
| „That is not a valid Paritr address“ | Same cause: addresses now start with P. Copy the address again from Wallet and set it on the node with ./manage.sh address P…. |
| Hash rate stays at 0 | Mining is disabled, the payout address is missing, or the intensity is set very low. |
| Block height stays at 0 | No connection to seed nodes. Check outbound connections and DNS, then ./manage.sh addpeer https://node0.oe-net.de. |
| unsupported hash type ripemd160 | Old node version. Update with manage.sh update – the current release ships its own implementation. |
| scrypt is not available at startup | The Python build has no OpenSSL support. Install the official Python package for your system; distribution packages compiled without OpenSSL cannot mine. |
| The chain does not start after an update | The data directory still holds blocks from an older consensus version. The node refuses to use it on purpose. Stop the service, delete data/ and start again – the chain is reloaded from the network. |
| Server gets very hot / loud | Reduce cores or intensity under hardware usage. |
| Mining reward not spendable | Coinbase maturity: 10 blocks. Until then it is listed as Pending. |
| The node mines but never finds a block | That is normal for small nodes and no longer a problem: what counts are the shares. Check under Mining › My share whether your share count is rising – then the payouts are flowing. |
| Own shares stay at 0 | The node is too young (the measuring window spans 120 blocks), it has no peers to report shares to, or it still runs a version before 5.0.0. |
| The node finds blocks but receives hardly any payouts | Its blocks are not being adopted by the other side. Bring all nodes to version 5.0.0 or newer, synchronise the system clock via NTP (timestamps that are too old violate the median-time-past rule) and check that public_url is set and reachable. |
| Peer reports „coinbase does not match the share distribution“ | The nodes involved run different consensus versions. Bring all of them to 5.0.0 with manage.sh update or manage.ps1 update. |
| The peer list contains unknown IP addresses | Those are the A records of the DNS seed – for a node behind a CDN, the provider’s edge addresses, where the RPC port is not open. They are no longer accepted; existing entries can be removed with ./manage.sh rmpeer <url> or by deleting data/peers.json. |
| The main node shows 0 peers | Normal as long as the other side reports no reachable public_url: they dial the main node, not the other way round. The number of counterparts is in network_nodes resp. inbound_count. |
API reference
Every node exposes an open JSON/REST interface. Admin endpoints expect the X-Admin-Secret header.
| Endpoint | Description |
|---|---|
| GET /status | Full network and node status |
| GET /health | Short reachability check |
| GET /chain/params | Consensus parameters including share and emission rules |
| GET /supply | Circulating supply, emission and inflation rate |
| GET /address/<address> | Balance and next nonce |
| GET /address/<address>/transactions | Ledger entries of an address |
| POST /transaction | Submit a signed transaction |
| GET /transaction/<txid> | A single transaction |
| GET /block/<height|hash> | Fetch a block |
| GET /fee/estimate | Fee recommendation |
| GET /mining/info | Mining state, share difficulty, hardware budget |
| GET /mining/rewards/<address> | Your own credits |
| GET /mining/distribution | Aggregated pool figures (optional ?address=) |
| GET /state/snapshot | Verifiable account snapshot at the last state checkpoint |
| GET /p2p/whoami | The public address a peer sees you under |
| POST /p2p/share | Submit and relay a share (JSON) |
| POST /p2p/share/bin | Same, in binary framing |
| POST /p2p/block/bin | Submit a block in binary framing |
| POST /admin/mining | Set address, mining, cores and intensity |
| GET /admin/peers | Peer list with state |
| POST /admin/sync | Trigger a chain sync |
Example
curl -s http://127.0.0.1:5050/mining/info | python3 -m json.tool
curl -s -X POST http://127.0.0.1:5050/admin/mining \
-H "Content-Type: application/json" \
-H "X-Admin-Secret: YOUR-SECRET" \
-d '{"mining_processes": 2, "mining_intensity": 60}'