Documentation
PowMachina — the chain specification
Status: these are the parameters of the running testnet. They can still change before mainnet’s genesis; the numbers are justified, not voted on. The PoW algorithm has its own document: the MachinaHash algorithm.
1. What it is
A new PoW chain from scratch (not a fork), designed so that CPU and GPU miners both have a guaranteed share of the emission and so that ASICs/FPGAs have no return on investment. The guarantee is not in the algorithm but in consensus: mining lanes, each with its own difficulty and the same block reward.
| Name | PowMachina |
| Ticker | POWM |
| Smallest unit | cog, 1 POWM = 10^8 cogs |
| Consensus | PoW, 2 lanes: lane C = MachinaHash-C (RandomX v2), lane G = MachinaHash-G (B-core + DAG) |
| Account model | UTXO |
| Signatures | secp256k1 + Schnorr (BIP340), verification in internal/mh (the only implementation) |
| Addresses | bech32m (BIP350), HRP powm → addresses start with powm1…; the script version is the first data character, the program is a 32-byte key |
| Scripting system | a subset of Bitcoin Script (known semantics, existing tooling) |
2. Emission and tokenomics
| Parameter | Value | Why |
|---|---|---|
| Block time (network) | 30 s | a share settles within a block, so a small miner sees its credit within a minute (the Sharepool); throughput is set by the block size, not the speed (§2.2) |
| Block time (per lane) | 60 s | 2 lanes × 60 s = 30 s |
| Max block size | 96 kB | 3.2 kB/s → 101 GB/year at 100 % fill, of which transactions get what the coinbase leaves (72 kB, 2.4 kB/s) |
| Block reward | 10 POWM | the same in every lane |
| Halving | every 4,200,000 blocks (≈ 4 years) | 4,200,000 × 30 s = 3.99 years |
| Sum of the halvings | 84,000,000 POWM (the sum of the halvings, not a cap) | 10 × 4,200,000 × 2 = exactly 84 M; the slow start takes off ≈ 100,000 POWM |
| Tail reward | 0.24975 POWM/block = 0.999 POWM every 2 minutes from the point where halving would drop below it (~year 24) | miners have an income even with cheap fees; the ASCII sum of “PowMachina” = 999 (the tail emission), in the code TailSubsidy |
| Sanity cap on sums | 1,000,000,000 POWM (MaxMoney) |
only overflow protection when summing, not an emission cap |
| Premine | 0 | a fair launch; for a new coin credibility is more expensive than a premine |
| Dev fee | 5 % of the subsidy up to block 2,100,000 (≈ 2 years) | funds development without a premine; it ends by itself (§2.1) |
| Slow start | for the first 20,000 blocks the reward rises linearly 0.1 → 10 POWM | anti-instamine (≈ 7 days) |
| Coinbase maturity | 400 blocks (≈ 3.3 h) | |
| Transaction fee | a dynamic fee market, min relay 1,000 cogs per 1,000 units of weight; weight = max(bytes, storage mass with C = 10⁹) | an ordinary payment pays for bytes only, tiny outputs pay for their space in the UTXO set |
| Storage mass (consensus) | KIP-9, C = 10⁸, a cap of 64,000 per block including the coinbase (the template leaves 16,000 for the coinbase) | protection against dust spam in consensus, not only in the mempool (fees, dust and the UTXO set) |
The emission profile:
| Period | Blocks | Reward | Emitted | Cumulative |
|---|---|---|---|---|
| 1 (0–4 y) | 4,200,000 | 10 | 42,000,000 | 42,000,000 |
| 2 (4–8 y) | 4,200,000 | 5 | 21,000,000 | 63,000,000 |
| 3 (8–12 y) | 4,200,000 | 2.5 | 10,500,000 | 73,500,000 |
| 4 (12–16 y) | 4,200,000 | 1.25 | 5,250,000 | 78,750,000 |
| … | … | … | … | → ~84 M, then 0.24975 POWM/block forever |
The halving comes every 4 years, not every 2: the block reward stays relevant for longer, so the network’s security does not depend on a fee market before one even exists.
2.1 The dev fee
| Parameter | Value |
|---|---|
| Rate | 5 % of the block subsidy (DEV_FEE_BPS = 500) |
| Validity | blocks 1 – 2,099,999 (≈ 2 years; then 0 %, hardcoded in consensus) |
| Volume | 1,045,001 POWM (5 % of the subsidy up to block 2,100,000; the slow start takes off the rest) |
| Source | the subsidy only, not transaction fees — those belong entirely to the miner |
| Slow start | the fee is computed from the current (reduced) subsidy, not from the full one |
| Enforcement | the coinbase must contain an output of exactly floor(subsidy × 500 / 10000) to DEV_FEE_SCRIPT as its first output; otherwise the block is invalid |
| Address | one 32-byte key (an ordinary version 0 output), generated offline and never held on a server |
| Changing the address | only by a hard fork — no on-chain upgrade mechanism, no “the dev can redirect the fee” |
Why this way and not another:
- Premine 0. A dev fee from the emission is more transparent: it is paid continuously, it is visible in every coinbase and it expires by itself after two years. A premine is a one-off act of trust up front.
- The time limit is what matters. A permanent dev fee is an argument against a coin at every listing and in every discussion. A two-year one, with its end date written into consensus from genesis, is not. The dev fee ends at block 2,100,000, that is halfway to the first halving.
- From the subsidy only — a miner never loses part of the fees, so the dev fee does not change the fee market.
- 5 % is in the lower half of what other coins do (Zcash had 20 % / 4 years, Beam 20 %, Firo 15 %, Ergo ~4.4 %) — it can be defended without explaining.
2.2 A chain’s growth — what really drives it
Not the block time. It is driven by throughput = max block size ÷ block time:
| configuration | blocks/year | kB/s | GB/year (full blocks) | MB/year (empty) |
|---|---|---|---|---|
| 1 s / 256 kB | 31.5 M | 256 | 8,273 | 10,698 |
| 60 s / 2 MiB | 526 k | 34.1 | 1,103 | 178 |
| 30 s / 96 kB (chosen) | 1.05 M | 3.2 | 101 | 323 |
| Bitcoin (1 MB / 600 s) | 53 k | 1.71 | 55 | 18 |
A 60 s / 2 MiB chain would grow by 1.1 TB a year at full utilization. The chosen configuration is under twice Bitcoin’s throughput, and transactions get 2.4 kB/s of it. Until the chain has demand, the blocks themselves (headers and empty coinbase transactions) grow by ~323 MB/year — 307 B per block (an 89 B header + a 218 B body). The shares a block settles come on top (the Sharepool, §6) and can be pruned once final.
A node takes up more on disk — besides the blocks it stores the UTXOs (2 new coins from every
coinbase), the undo data and the height index: ~700 B per block ≈ 736 MB/year at 30 s. With
-txindex -addrindex (the explorer) ~941 B per block ≈ 990 MB/year. That is the logical size before
Pebble’s compression; hashes barely compress, so on disk it is realistically a little less. For
users the number is “under 1 GB a year” before the shares.
2.3 What keeps the ballast out
Ballast is not stopped by format bans — those always get worked around — but by price and the block cap:
| Rule | Value | Effect |
|---|---|---|
| No witness discount | 1 byte = 1 byte | closes the path through which inscriptions got into Bitcoin (there the witness costs 1/4) |
| Max block | 96 kB | storing 1 MB of data = eleven full blocks at full price |
| Dust limit | 10,000 cogs (0.0001 POWM) | keeps the UTXO set small — the UTXO set has to be in RAM, block data does not |
| Pruning | on by default, archival is opt-in | an ordinary node keeps only the UTXO set + the recent blocks |
| OP_RETURN | max 80 B, once per transaction | enough for a hash/anchor, not enough for storing data |
| Min relay fee | 1,000 cogs/kvB | spam has a price |
2.4 Room reserved for future development (contracts)
The limits in §2.3 concern data, not code — more complex scripts stay possible: the limit is not 520 B per item (as in Bitcoin) but 10 kB per script and 16 kB per input, which covers a covenant script and a zk proof.
So that contracts can be added by a soft fork, not a hard fork, four things are reserved from genesis that cost not a single byte until they are used:
- Script versioning. Every output carries a version.
v0= a key; versions 1–15 are reserved: an output of one can be neither created nor spent until a fork (§3.5) defines the version (strict-outputs). A new script type — contracts, covenants, zk verification — arrives as a new version without the transaction format changing. They are not left spendable by anybody until then, as a soft-fork path would have it: whatever was sent to such an output by mistake would belong to the first miner to notice. - Reserved opcodes in the
OP_SUCCESSstyle — new operations activate without changing the transaction format. - A commitment slot in the coinbase. A reserved structure (the same principle as the segwit commitment in Bitcoin) for a future state root, utreexo or zk commitment. This is the essential one: stateful contracts need a commitment to the state — if no room is left for it, the block header has to change, which is a hard fork. Until the slot is used, it has zero size.
- Signalling bits in the header’s
versionfor soft-fork activation (the BIP9 model).
What is deliberately not being done now: no VM, no state model, no accounts. Things can be added, not removed — and every byte of format introduced “just in case” is carried by the chain forever.
3. Consensus — the parameters
| Parameter | Value |
|---|---|
| PoW | lane C: MachinaHash-C = RandomX v2 with the PowMachina salt (a 2.1 GiB dataset) · lane G: MachinaHash-G = BLAKE3 + a B-core over a 1–8 GiB epoch DAG |
| Lanes | C (CPU-weighted), G (GPU-weighted) |
| Share of blocks | 1/2 per lane, enforced by the per-lane retarget |
| Retarget | per lane, every block: the lane’s last target × 2^(how far the lane is behind its 60 s pace / 1 h), measured on the clock of the whole chain (§3.6) |
| Lane rotation | at most 2 blocks of the same lane in a row; waived when the gap from the parent block exceeds 300 s |
| Chainwork | normalized per lane by a geometric mean (the MultiShield model) |
| Epoch | 20,000 blocks (≈ 6.9 days) — the DAG grows and a new RANDMATH sequence is derived |
| Timestamp | not before the parent’s, at most +30 s into the future (§3.6) |
| Max block size | 96 kB serialized, with no witness discount (1 byte = 1 byte) |
| Coinbase | up to 24 kB — room for 400 payouts of the Sharepool (the Sharepool, §5.2). A centralized pool does not need that: it pays from its own wallet |
| Witness | separate from the txid from genesis (no malleability, no legacy debt) |
| A node’s memory | a full node holds the full DAG (≈1 GiB) — light verification is orders of magnitude slower and is meant for SPV (the algorithm, §2.2) |
| Reorg limit | 2,000 blocks ≈ 16.7 h (a hard cap) |
| Reorg scoring | MESS (the ECIP-1100 model) over the normalized chainwork — a deep reorg requires up to 31× the work (security, §3) |
| Siblings | two blocks on the same parent: the lower block ID, unless the other leads by more than 1,000 share units of votes (the Sharepool, §4) — a node’s preference, not a validity rule |
| Finality | the miners of the last 2,880 blocks, more than 2/3 of their weight, at a depth of 80 blocks (~40 min) — a confirmed block is never rewritten. Each lane holds half of the weight; the quorum can neither produce a block nor stop the chain (finality) |
| DAG | 1 GiB in epoch 0, +4 MiB/epoch, a cap of 8 GiB (≈ 34 years) |
3.1 The block header (89 B)
| field | size | in the PoW input |
|---|---|---|
version |
4 B | yes |
prev_block |
32 B | yes |
merkle_root |
32 B | yes — the share root (§3.2) |
time |
4 B | yes |
bits |
4 B | yes |
height |
4 B | yes |
nonce |
8 B | enters the hash separately |
lane |
1 B | enters the hash separately |
The PoW input is therefore the first 80 B; the nonce and the lane are added to the hash separately, so a nonce found in one lane is useless in another. The height is in the header deliberately — it determines the DAG epoch, so the two cannot be swapped without changing the PoW.
version carries the header version in its lower half and the fork signal bits in the upper
half (§3.5).
The block ID = BLAKE3 over all 89 B with its own domain. The definition lives in internal/mh
(mh1_block_id), so that this hash too has a single implementation.
3.2 Transactions and the block
A transaction has no scriptSig. The signatures live in a witness that does not enter the txid
— malleability is therefore excluded by construction, not by a patch.
txid |
BLAKE3("PowMachina/txid/v0" ‖ the transaction without the witness) |
wtxid |
BLAKE3("PowMachina/wtxid/v0" ‖ the transaction with the witness) — covers the signatures too |
| Block | the header (89 B) ‖ the share commitment (66 B) ‖ the settlement body (the Sharepool, §3.1, at most 256 kB) ‖ the transaction count (4 B) ‖ the transactions (with the rest at most 96 kB) |
| Share commitment | payout (32 B, the program of a version 0 address) ‖ finality_key (32 B, zeros = none, finality, §2) ‖ threshold (1 B) ‖ weight (1 B, at most 11) — the Sharepool, §2 |
merkle_root |
BLAKE3("PowMachina/share/v1" ‖ body_root ‖ the share commitment), body_root = BLAKE3("PowMachina/body/v1" ‖ the merkle root over the txids ‖ BLAKE3("PowMachina/settlement/v1" ‖ the settlement body)) |
| Coinbase commitment | the coinbase’s last output: a data output whose script is exactly "PMwc" ‖ the merkle root over the block’s wtxids ‖ "PMcr" ‖ the root of the credit state the block builds on (72 B, the Sharepool, §5.1). The coinbase’s own leaf is 32 zero bytes and the coinbase carries no witness |
| Limits | 1,000 inputs, 1,000 outputs, a 10 kB script, a 16 kB witness per input |
| Script versions | 0 is the basic one; 1–15 are reserved for future types (the soft-fork path, §2.4); higher ones are invalid |
| Data output | version 0xff, the value has to be 0, at most 80 B and one per transaction; it does not enter the UTXO set |
| Coinbase | the first transaction; its PrevTxID is the height (8 B) and 24 B of free space for the miner (an extranonce). Its outputs are exactly: the dev fee, the payouts the credit state owes in the order of its queue (the Sharepool, §5.2), the commitment — nothing else. A block pays its miner through credits, not an output |
| Dev fee | the coinbase’s first output, the value has to match exactly (not “at least this much”) |
The Merkle tree differs from Bitcoin’s in two things: the leaves and the internal nodes have different domains, and with an odd count the last node is promoted unchanged. Duplicating the last node is the cause of CVE-2012-2459 — two different transaction lists lead to the same root.
The share commitment is what makes a block a share (the Sharepool, §2): the miner’s payout, finality key, payout threshold and share weight are under the PoW together with the transactions. Whoever relays a block or a share cannot redirect it, and a block’s finality key cannot be swapped in a copy of it.
The witness commitment closes what the txid leaves open. The header’s merkle root is built
over txids, so by itself the block id says nothing about the signatures: whoever passes a block on
could change one and the body would still match its header. With the commitment in the coinbase —
which is under the header’s merkle root — the header vouches for the witnesses too and stays 89 B.
A node checks it the moment a body arrives, with no UTXO set: a body whose witnesses do not hash to
the commitment is not the block the miner made and is turned away before it is stored. A block
without the commitment is invalid. Checking the witnesses against it is a fork (§3.5,
witness-commitment, bit 0): on from the genesis on a new network.
The credit root in the same output commits to the credit state the block builds on — the state its parent left, before this block’s payouts — so the coinbase depends on nothing the miner chooses and one template serves every miner. A light wallet proves its credit against it one block later (the Sharepool, §5.1).
The serialization is canonical: every transaction and every block has exactly one valid form and trailing bytes are rejected. Freedom in encoding is a path to implementations diverging.
3.3 Spending and signatures
The only output type today is version 0 = a 32-byte x-only key, spent by a single 64-byte
Schnorr signature (BIP340). Verification lives in internal/mh, so that signatures too have a
single implementation — a difference in an edge case between two libraries would split the network.
A version 0 output is exactly 32 bytes (strict-outputs): any other length could never be
spent and would sit in every node’s UTXO set for good.
The sighash commits to all the inputs including their amounts and scripts and to all the
outputs. The amounts are in there deliberately: without them a different input value can be slipped
to the signer and a fee lured out of them (the reason BIP143 came about). There is a single mode,
the equivalent of SIGHASH_ALL; further modes are needless surface for bugs and, if needed, will
arrive through a new script version.
The signature is bound to the network (signed-network): the id of the network’s genesis block
opens the signed message, under the tag PowMachina/sighash/v1. Without it a transaction signed on
one network is valid on any other where the same outputs exist — and somebody else can make them
exist, since a coinbase can pay any key. The genesis id rather than the network magic, because it
differs for every network there has ever been.
Lock time and sequence (locktime). LockTime is a height: the transaction may go into a
block at that height or above; zero is no lock. There is no lock by wall-clock time — at 30 s a
block a height says the same and needs nothing but the block’s own header to check. Sequence is
reserved and has to be zero; it stays in the format and under the signature so a later rule can
give it a meaning (a lock relative to the spent output, which payment channels need) without the
layout of a transaction changing. A locked transaction is not held in the mempool.
All four rules of this section and §3.2 are forks (§3.5), on from the genesis on every network. A transaction is signed and checked against the rules of the block it goes into.
3.4 The mempool — policy, not consensus
The mempool’s rules are stricter than consensus and a node may have its own. Hence the things that belong here are the ones that keep the UTXO set small and spam expensive but do not decide a block’s validity:
| Rule | Value |
|---|---|
| Minimum fee | 1,000 cogs/kB |
| Dust limit | 10,000 cogs (a smaller output costs more in the UTXO set than it carries) |
| Mempool cap | 64 MB / 20,000 transactions; when full, the cheapest are evicted |
| Chaining | a transaction may spend the output of another transaction from the mempool; they go into a block in the right order |
| Expiry | 72 h from acceptance (descendants included — a child without its parent is invalid) |
| Surviving a restart | <datadir>/mempool.dat; after loading, every transaction goes through Accept again |
| Orphan pool | 100 transactions / 4 MiB / 20 min; a child that overtook its parent is set aside and the parent is requested |
3.5 Adding a rule after the genesis
A consensus rule that was not there at the genesis starts at a height, and the height is part
of the network’s parameters (NetParams.Forks). The block at that height is the first one checked
against the new rule. Nothing else switches a rule on — not a clock, not a vote, not a quorum — so
two nodes running the same release always agree on what a block is checked against.
Every network has its own table: a rule gets a height on regtest, then on testnet, and on mainnet only after it has run there. A new network can start with a rule on by giving it height 0.
Signalling. The header version is split in two: the lower 16 bits are the header version
itself (1), the upper 16 are signal bits, one per rule. A miner sets the bit of every rule its
software knows and that is not active yet; once the rule is active the bit is left out again. The
node puts the right version into the work it hands out (gettemplate, stratum), so a pool or a
miner signals by running a release that has the rule.
The node only counts the bits — over the last 4,000 blocks and per lane (getforks). That
is what a height is chosen by: a rule should not be given a height while one of the lanes is
mostly on software that does not have it. Signalling activates nothing. There is deliberately no
threshold that switches a rule on by itself: with a guaranteed share of blocks per lane it would
have to hold in each lane separately, and a fix for a security hole must not be something a part
of the hashrate can hold back.
A bit that a node has no rule for and that shows up in getforks (known: false) means the
network is getting ready for a release this node does not run yet.
3.6 The lane retarget and block time
These are the rules of the lane-difficulty fork (§3.5), which every network has from height 0.
The retarget. Every lane has its own target, recomputed for every block
(internal/chain/asert.go):
behind = time(tip) − time(the block the lane's last block was built on) − 60 s
− 300 s if the lane's last block was let in by the rotation relief
behind = clamp(behind, −4 h, +4 h)
target = target(the lane's last block) × 2^(behind / 1 h) capped at the network's floor
- The clock is the chain’s, not the lane’s.
tipis the block being built on, whichever lane it is. While one lane is silent the other keeps the time moving, so the silent lane gets easier at the speed of real time. A retarget that only looks at the lane’s own blocks cannot do that: it takes 9.5 h to follow a lane that lost 90 % of its hashrate, and never follows one that lost 99 %. - The relief wait is not counted. A lane mining alone gets one block per 300 s whatever its hashrate is. Counted as solve time that reads as a lane that lost its hashrate, and the lane slides to the floor — at which point the lane that is supposed to hold the chain is free.
- One gap moves a lane by at most 16×, either way. A lane that was gone for days comes back sixteen times easier than it left, not on the floor; a lane that really lost more gets there in the next gap.
- The genesis is outside time. It is written before the network starts, so where the formula would read the time of the genesis it reads the time of block 1. A lane without a block yet starts from the genesis target and follows the same formula, so an initial difficulty set too high for a lane comes down by itself.
- 2^x is the cubic of aserti3-2d (Bitcoin Cash, 2020) in 16.16 fixed point, integers only; the
fixed results are in
TestAsertVectors.
The half-life and the cap were picked by simulation (cmd/powm-diffsim): a 30 min half-life swings
the difficulty of a chain at rest too much, 2 h takes six hours to follow a lane that lost 90 %,
1 h swings it about as much as an LWMA window does and follows in three. Both are measured in time,
not in blocks, so they do not depend on the block time; at a 30 s block the difficulty of a chain
at rest swings by about 7 %.
The rotation relief, 300 s (powm-diffsim -spacing 60 -relief N): at a 60 s lane it lets a
third block of a lane at rest through in 0.03 % of blocks (225 s: 0.13 %, 150 s: 0.66 %); with one
lane gone the chain makes a block every 6 minutes (900 s would leave it at 16); and a lane that
lost 99 % makes the other one 2.25× easier at the worst (900 s: 4.7×).
Block time. A block is not dated before its parent (the same second is allowed) and at most 30 s ahead of the validating node’s clock. A looser bound — above the median of the last eleven blocks and 120 s ahead — would let a block be dated some twelve minutes back; the next block of the lane would then look twelve minutes late and the lane’s difficulty would fall — a third of a lane doing that would run the lane 40 % faster than its hashrate allows, and the same room would let a miner skip most of the rotation relief. With these bounds a third block of the same lane needs at least 270 s of real time. A block dated the full 30 s ahead makes a lane look 30 s late, which eases it by 2^(30/3600), 0.6 %.
4. Network parameters
| mainnet | testnet | regtest | |
|---|---|---|---|
| P2P port | 7696 | 17696 | 27696 |
| RPC port | 7697 | 17697 | 27697 |
| HTTP block mirror | 7698 | 17698 | 27698 |
| stratum | 7699 | 17699 | 27699 |
/metrics (opt-in) |
7694 | 17694 | 27694 |
| Magic bytes | 50 57 4D 31 (PWM1) |
50 57 4D 54 |
50 57 4D 52 |
| bech32m HRP | powm |
tpowm |
rpowm |
| address shape | powm1q… |
tpowm1q… |
rpowm1q… |
| Default DNS seeds | none yet — 3–5 domains at different people before genesis (security, §5) | seed-t1.powmachina.com, seed-t2.powmachina.com |
— |
| Genesis | to be fixed before launch | 1e7c79f3…169de230 (2026-10-23 08:00 UTC) |
03c4ab1d…2c48c2fc |
| Difficulty at launch | the floor 1f00ffff = 65,536 hashes per block |
the same as mainnet | 2000ffff = 256 |
Testnet runs on the mainnet parameters (a 1 GiB DAG that grows, the same difficulty floor) — it is meant to measure what will one day run for real. The genesis has no PoW and no body: consensus does not verify it, it is the root of trust from the binary, and searching for a nonce for it would be theatre. The first blocks go at the floor, that is seconds of work, and the retarget pulls them towards the 60 s target per lane.
A node picks its network with a flag: -testnet, -regtest. Without a flag it refuses to
start — the mainnet genesis does not exist and a placeholder should not be usable by mistake as
the root of a real network.
- The port scheme: 7696 = “POWM” on a phone keypad, testnet 1xxxx, regtest 2xxxx, the last digit
= the service. All 12 are free in the IANA registry, they do not collide
with BTC, LTC, DASH, XMR, KAS, ETH or DOGE, and they are below 32768 — above that Linux
allocates outgoing connections and the port could be taken after a restart (
TestPortSchemeguards this). The project rule applies: ports are not translated in Docker —7696:7696, neverX:7696. - SLIP-44
coin_type: 9797’ for now, to be submitted as a PR tosatoshilabs/slipsbefore mainnet. - The
powmprefix is part of the coin’s identity — the address shows which network it is for. It may only be changed before genesis; afterwards it would break compatibility with every wallet. - The wallet: BIP39 24 words → BIP32, account
m/44'/9797'/0', receiving…/0/i, change…/1/i. A private key for export ispowmsec1…(bech32m, the network prefix +sec). The file, the format and the RPC: the wallet.
5. Genesis
It will be fixed only after the algorithm is calibrated. What it will contain:
- a coinbase message (the text will be chosen later; it should reference something verifiably dated),
timestamp,nonce,lane = C,- the initial difficulty per lane — set so that the first block falls within ~2 minutes on an ordinary desktop,
- the genesis coinbase output: unspendable (a fair launch, a zero premine).
6. Architecture and repositories
The powmachina monorepo. The reason: the algorithm and the node have to be
version-locked — a one-constant difference between them = a network fork.
powmachina/
├── go.mod one Go module — `go build ./cmd/powmachinad` and that is it
├── cmd/powmachinad/ the node (consensus, P2P, UTXO, mempool, RPC)
├── cmd/mh-bench/ the calibration harness (the CPU side of the gate)
├── cmd/mh-vectors/ the test vector generator
├── cmd/mh-dumpdag/ fixtures for the CUDA tests
├── cmd/mh-refvals/ reference values of the primitives for the CUDA tests
├── internal/mh/ MachinaHash — the only implementation of the algorithm
├── internal/randomx/ the cgo wrapper over RandomX v2 (MachinaHash-C)
│ └── csrc/randomx/ the vendored upstream — see VENDOR-RANDOMX.md
├── internal/chain|store|blocksync|p2p|rpc|wallet|hd|address/
├── machinahash-cuda/ the lane G CUDA kernel (bit-exact against the vectors)
├── pm-pool/ the stratum server (variants per lane)
├── pm-explorer/ the block explorer
├── docs/ [specification](/docs/spec/), [the MachinaHash algorithm](/docs/algorithm/)
├── docker-compose.yml the node + the explorer; data in ./data/<service>/ (gitignored)
├── versions.env
└── .github/workflows/ the release builds for Linux and Windows
The languages — the reasoning:
- Everything in Go, one module. A node runner opens GitHub, sees
go buildand has nothing to figure out. A second toolchain in the repo is a question (“why?!”) that is better not to have. - The algorithm is written once (
internal/mh) and both the node and the miner call it directly. The most common cause of death of a new chain is a consensus disagreement between two PoW implementations — this way one cannot arise. The test vectors are the contract: every implementation detail is checked against them. - C++ is in the tree exactly once: the vendored RandomX. We do not rewrite it — not even into
Go. It is compiled through cgo during
go build, so the only extra requirement is a C compiler. - The GPU side in CUDA + OpenCL, validated bit-exact against
internal/mhin CI.
7. Roadmap
| Phase | Content | Output / gate |
|---|---|---|
| F0 | this spec | the parameters signed off |
| F1 | the algorithm core: the B-core, the lanes, the DAG, light verification, the test vectors | done — 1,000 vectors, CI |
| F2 | the benchmark harness, measurement on a real CPU | done — gate 3/3 on a Ryzen 9 7950X3D (the algorithm, §7.1) |
| F3 | the CUDA kernels, measurement on an RTX PRO 6000 + an RTX 3090 | done — the kernels are bit-exact against 1,000 vectors on both cards. Gate 2 (the B-core on a GPU) met (6000/EPYC 12.0×, lane G 785 GB/s = 44 % of the card’s ceiling). Gate 1 (the L-core on a CPU) not met (Ryzen/6000 = 0.47×) → the decision to use two algorithms (the algorithm, §7.5–7.6) |
| F4 | powmachinad: consensus including the lanes/rotation/chainwork, MESS, P2P (anti-eclipse per security, §4), UTXO, the mempool, RPC, the wallet, regtest |
in progress — done: the algorithm core (1,000 vectors match), the header, emission, the per-lane retarget, lane rotation, chainwork normalization, MESS, finality, P2P (framing, the addrman, the peer manager, TCP, the handshake), header and block body sync, the UTXO set with undo, validation including Schnorr signatures, the mempool and the RPC (including gettemplate for a pool and getfinality for an exchange). Transaction relay (inv/tx), the HD wallet (BIP32), bech32m addresses, finality attestation gossip and connection maintenance (feelers, anchor peers, slot filling). The wallet as a separate process (wallet-cli, wallet-rpc, BIP39, Argon2id). Bootstrap through DNS seeds. Missing (organizational): the seed domains, the mainnet genesis |
| F5 | a public testnet, the Sharepool, the explorer | running — the gate: the testnet holds its tip for 2 weeks without intervention |
| F6 | an external review of the algorithm + consensus, the genesis, mainnet | — |
| F7 | exchange integration: a wallet container, update and deployment monitoring, the listing | — |
Phases F1–F3 come before the node deliberately: if the calibration does not work out, only the algorithm changes, not the whole chain.
8. Plan B — used by half
Plan B said: if the calibration did not work out, the lane structure, the retargets, the rotation rule and the chainwork would stay exactly the same and only the cores would be swapped for established algorithms.
That is exactly what happened, and exactly how it turned out. Gate 1 failed (the algorithm, §7.5), so:
- lane C → RandomX v2 with the PowMachina salt. Used.
- lane G stays MachinaHash-G — gate 2 was met 17.3×, KawPow is not needed.
- a hybrid lane H as a tandem of the two: not used, there is no lane H (the algorithm, §7.7).
The lane architecture survived it without a single change to consensus other than the number of lanes. That was the whole reason it is described separately from the cores — and in practice it worked.
9. Decisions taken
- The ticker is POWM.
- Premine 0.
- Two lanes, no hybrid one (the algorithm, §7.7): with RandomX as the CPU half, the GPU half of a tandem comes for free, so it comes out 11× worse than C and G separately.
- A dev fee of 5 % of the subsidy for the first two years (§2.1), then 0 %.