ParallaxProtocol/xhash- the standalone C/C++ reference implementation (CMake build, Python bindings, and anxhash-benchmicrobenchmark tool). This is the recommended starting point for miner, pool, and tooling authors.kernel/xhash- the production Go implementation inside the Parallax daemon, which drives consensus on mainnet. The algorithm core lives inalgorithm.go, seal verification inconsensus.go, and difficulty adjustment indifficulty.goandasert.go.
1. Design goals
XHash was designed under four constraints:- Memory hardness. The dominant cost of a mining attempt must be pseudorandom reads over a multi-gigabyte dataset, so that performance is bounded by memory bandwidth rather than by arithmetic throughput. This keeps the gap between commodity hardware and custom silicon small.
- Asymmetric verification. Full nodes must be able to verify a block using only a small (megabyte-scale) cache and a few milliseconds of CPU time, without ever materializing the mining dataset.
- Standards-compliant cryptography. All hashing inside the algorithm uses the finalized NIST FIPS 202 SHA-3 functions, not the pre-standardization Keccak variants Ethereum shipped with. Any off-the-shelf cryptographic library can implement XHash without carrying a non-standard Keccak.
- Network isolation. The seed chain is domain-separated with a Parallax-specific constant, so no cache, dataset, or precomputed intermediate from any Ethash-family chain is reusable against Parallax, and vice versa.
2. Notation and conventions
- All multi-byte integers inside the algorithm are little-endian unless stated otherwise. Implementations on big-endian hosts must byte-swap 32-bit words at the storage boundary (the Go implementation marks on-disk files produced on big-endian machines with a
.besuffix). - A word is a 32-bit unsigned integer. A node (or item) is 64 bytes, i.e. 16 words.
sha3_256andsha3_512denote FIPS 202 SHA3-256 and SHA3-512 (standard padding0x06).keccak256denotes legacy Keccak-256 (padding0x01) and appears in exactly one place: the seal hash of the block header (Section 10).||denotes byte-string concatenation.A[i:j]denotes the half-open byte slice fromitoj.- All divisions on integers are floor divisions.
- Pseudocode is given in Python; it is executable against the prelude in the appendix of the Ethash page after substituting standard SHA-3 for Keccak.
3. Constants
PARALLAX followed by a single version byte 0x01:
3.1 Epoch schedule
With Parallax’s 600-second target block spacing, one epoch of 720 blocks spans exactly 432,000 seconds = 5.0 days. This matches Ethash’s original ~5-day cadence (30,000 blocks at 15 seconds), so operational assumptions about DAG regeneration frequency carry over unchanged. Approximately 73 epochs elapse per year, growing the dataset by about 612 MiB/year and the cache by about 9.6 MiB/year.3.2 Size derivation
Cache and dataset sizes grow linearly per epoch, but each is snapped down to the largest value whose node count is prime, eliminating the risk of short cycles in the pseudorandom parent-selection walk:datasetSizes and cacheSizes in algorithm.go. Because the growth constants and primality rule are identical to Ethash’s, the size tables coincide with Ethash’s tables; only the content of the structures differs.
4. Cryptographic primitives
Ethereum’s “sha3” is not SHA-3: it froze on a pre-standardization Keccak draft, and the final FIPS 202 standard changed the padding rule. XHash deliberately breaks with this legacy. Every hash inside the seed chain, cache, dataset, and hashimoto loop is standard FIPS 202 SHA3-256 or SHA3-512. This has two consequences:- Interoperability. XHash can be implemented against any compliant SHA-3 library (OpenSSL, libsodium via sha3 add-ons, hardware SHA-3 units, the Go standard library) with no custom Keccak code.
- Divergence by construction. Even for epoch 0, where the seed is all zeros in both algorithms (Section 5), the differing padding byte makes the very first cache node differ from Ethash’s, and the divergence cascades through every downstream structure. Network isolation does not depend on the chain magic alone; it is enforced at two independent layers.
5. Seed chain
Each epoch has a 32-byte seed from which its cache (and hence its dataset) is derived deterministically. Epoch 0 uses the zero seed; each subsequent epoch hashes the previous seed prefixed with the chain magic:s_0 = 0^32:
s_{e+1} = keccak256(s_e)) shares no seed with Parallax at any epoch, so precomputed caches and DAGs cannot be transplanted in either direction.
Note that implementations key their per-epoch structures by get_seedhash(epoch * EPOCH_LENGTH + 1), i.e. by any block strictly inside the epoch; all blocks of one epoch share one seed, cache, and dataset.
6. Cache generation
The per-epoch verification cache is produced in two phases: a sequential SHA3-512 chain fills the buffer, then three rounds of Sergio Demian Lerner’s RandMemoHash construction (from Strict Memory Hard Hashing Functions, 2014) scramble it so that computing any node quickly requires holding essentially the whole cache:word(node, k) reads the k-th little-endian 32-bit word of a 64-byte node and xor is the bytewise XOR of two nodes. The output is n 64-byte nodes (n = 262,139 at epoch 0). Cache generation costs roughly (CACHE_ROUNDS + 1) * n SHA3-512 invocations and takes on the order of a second on a modern CPU.
7. Data aggregation: FNV-1
Ethash mixes data with a function inspired by FNV but deviating from it: it multiplies the prime with a full 32-bit word instead of one octet at a time. XHash instead implements FNV-1 exactly as specified, consuming the second operand byte by byte (little-endian), with the first operand acting as the running FNV state:- Non-associativity and non-linearity in the state. Like Ethash’s variant,
fnv1is a cheap, order-sensitive combiner - a sequence of multiplies and XORs that does not commute and cannot be factored out of the access loop. - Full-width diffusion per octet. Each of the four input bytes is folded in through its own multiply, giving byte-level diffusion identical to the canonical FNV-1 avalanche behavior, and making XHash mixing traces incompatible with any Ethash implementation or hardware pipeline.
fnv1 is also used as the index generator for pseudorandom parent and dataset-page selection (Sections 8 and 9), so the change affects both the mixing arithmetic and the memory access pattern.
8. Dataset generation
Each 64-byte dataset node is computed from the cache by aggregatingDATASET_PARENTS = 256 pseudorandomly selected cache nodes:
j+1 before finishing read j. Full dataset generation performs full_size / 64 node computations and is embarrassingly parallel across nodes; the Go implementation generates it on all cores and typically completes in minutes, while miners are expected to pregenerate the next epoch’s dataset in the background (Section 12).
9. The hashimoto loop
The core sealing function binds a header to a nonce by aggregating 64 pseudorandom 128-byte pages of the dataset:- Each access fetches a full aligned 128-byte page (two adjacent nodes), sized to a DRAM burst so that every iteration performs one full-page read; this minimizes TLB-miss advantages that specialized hardware could otherwise exploit.
- The page index for iteration
idepends on the mix produced by iterationi-1, so the 64 reads are strictly serial per attempt; throughput scales with memory bandwidth and parallel attempt count, not with faster arithmetic. - The final outer
sha3_256(s || cmix)serves two purposes: it makesresulta statistically unbiased 256-bit value, and it creates a cheap outer PoW - a peer can hashs || cmixand compare against the target before doing any dataset or cache work, which is useful for DoS filtering.
10. Header binding: the seal hash
The 32-byteseal_hash input to hashimoto commits to the entire block header except the two seal fields themselves. It is the legacy Keccak-256 of the RLP encoding of the truncated header:
mixHash and nonce are excluded (they are outputs of sealing, not inputs). epoch_start_time is a Parallax-specific header field recording the timestamp of the most recent retarget boundary block; it participates in difficulty validation (Section 13) and is therefore sealed. The 64-bit nonce is stored big-endian in the header (Ethereum convention) but serialized little-endian into the 40-byte hashimoto input.
11. Mining and the target
A nonce is valid for difficultyD when the hashimoto result, interpreted as a big-endian 256-bit integer, satisfies:
(2^256 - 1) // D rather than Ethash’s 2^256 // D. Using the maximum representable 256-bit value as the numerator keeps every quantity in the system - targets, difficulties, and the ASERT max_target bound (Section 13) - inside native 256-bit arithmetic with no 257-bit intermediate, which simplifies fixed-width implementations. At D = 1 the target is 2^256 - 1 and every hash is valid; difficulty and target are related by D = (2**256 - 1) // target in the reverse direction.
Miners draw the starting nonce from a cryptographically seeded 64-bit source and scan linearly; the Go sealer distributes disjoint starting points across threads and re-randomizes per work package.
12. Verification
A block seal(mixHash, nonce) is verified as follows:
- Recompute
seal_hashfrom the received header (Section 10). - Evaluate hashimoto. A full verifier with the current DAG uses
hashimoto_full; a light verifier useshashimoto_light, which regenerates only the 128 dataset nodes actually touched (64 pages × 2 nodes), each costing 256 cache-node FNV walks and two SHA3-512 calls. Light verification needs only the ~16 MiB cache and runs in single-digit milliseconds. - Reject with
invalid mix digestunless the computedmix_digestequals the header’smixHash. This check ensures the miner actually performed the memory-hard inner loop and lets verifiers reject forgeries before the target comparison. - Reject with
invalid proof-of-workunlessresult <= (2**256 - 1) // difficulty.
fulldag fast path), never blocking block import on DAG generation.
12.1 Operational notes (caches and DAGs on disk)
The Go implementation memory-maps caches and datasets from disk and maintains, for each, the current epoch plus a pregenerated future epoch so that the epoch transition at multiple-of-720 heights causes no mining stall. Files are named:R23 is the data-structure revision (algorithmRevision = 23); a .be suffix marks big-endian hosts. Each file begins with the magic words 0xbaddcafe, 0xfee1dead as a sanity check, and stale epochs beyond a configured retention count are deleted automatically. Remote miners and pools receive work packages containing the seal hash, the epoch seed hash, the 32-byte big-endian boundary target (2^256 - 1) // D, and the block number.
13. Difficulty adjustment
Difficulty adjustment is not part of the hash function proper, but it defines the target against which XHash results are judged, so it is specified here. Parallax uses two regimes, split at the chain-configuredasertActivationHeight (17,560 on mainnet).
13.1 Nakamoto phase (heights below activation)
Blocks before activation retarget exactly like Bitcoin, adapted to header-carried state. Every header carriesepoch_start_time: on a boundary height (h % 2016 == 0) it is set to that block’s own timestamp; otherwise it is copied from the parent. At each boundary:
actual spans the 2,015 intervals from the boundary block to the parent while being compared against a 2,016-interval budget, the measurement mirrors Bitcoin’s historical off-by-one exactly.
13.2 ASERT phase (heights at or above activation)
From the activation height onward, Parallax switches to aserti3-2d, the absolutely scheduled exponentially rising targets algorithm adopted by Bitcoin Cash, computing every block’s target directly from its schedule deviation against a fixed anchor:p against the anchor block A (the block at height activation - 1):
time_delta = p.timestamp - timestamp(parent of A)height_delta = p.height - A.height- ideal spacing is 600 seconds, and the half-life is 172,800 seconds (2 days): sustained arrival one half-life ahead of schedule doubles difficulty; one half-life behind halves it.
2^x from the BCH specification (coefficients 195766423245049, 971821376, 5127), and the result is clamped to max_target = 2^256 - 1. The implementation caches the anchor and re-derives it if a reorg replaces the header at the anchor height. Difficulty and target convert through D = (2**256 - 1) // T as in Section 11.
14. Differences from Ethash
The structural parameters were retained deliberately: they are the well-studied, battle-tested part of Ethash. Every cryptographic and arithmetic ingredient feeding those structures was replaced or corrected.
15. Security considerations
Memory hardness. A single hashimoto evaluation performs 64 serial 128-byte reads at pseudorandom, data-dependent addresses over a dataset that exceeds on-chip SRAM budgets by orders of magnitude. Amortizing the dataset away (a “light evaluation” attack) costs 128 node regenerations, each requiring 256 sequentially dependent cache reads plus two SHA3-512 calls - roughly three orders of magnitude more work per attempt than a dataset read, which makes cache-only mining strictly uneconomical while keeping cache-only verification cheap (it runs once per block, not once per nonce). ASIC and infrastructure isolation. Divergence from Ethash is enforced at three independent layers: (1) FIPS-202 padding changes every hash output even under identical inputs; (2) the chain magic makes every seed from epoch 1 onward Parallax-specific; (3) octet-wise FNV-1 changes both the mixing arithmetic and the pseudorandom address streams. Fixed-function Ethash hardware pipelines the Keccak permutation with draft padding and word-wise FNV in silicon; neither can be reconfigured to XHash, and no Ethash DAG, cache, or seed table is reusable. Verifier DoS resistance. The outersha3_256(s || cmix) allows a cheap plausibility check on received seals before any memory-hard work, and the mix-digest equality check (Section 12) forces attackers to perform the full inner loop to produce a header that survives past step 3.
Epoch-0 caveat. The zero seed of epoch 0 is shared with Ethash by construction, but layer (1) alone already guarantees the epoch-0 structures differ; network isolation never rests on the seed chain alone.
16. Calculations
This section quantifies the security and control-theoretic behavior of XHash under Parallax’s parameters, in the spirit of Section 11 of the Bitcoin whitepaper. Every number below was verified numerically against a bit-exact port of the consensus integer arithmetic inasert.go (including Go’s truncating division, two’s-complement uint64 wraparound, and arithmetic shifts); the probabilistic results were evaluated in log-space to full float precision.
16.1 The double-spend race
Following Nakamoto, model the contest between the honest chain and an attacker’s private chain as a binomial random walk:p is the probability the next block is honest, q = 1 - p the probability it is the attacker’s. By the Gambler’s Ruin argument, an attacker who is z blocks behind catches up with probability
z: each additional confirmation multiplies the attacker’s odds by q/p. A recipient who waits for z confirmations must also account for the progress the attacker has already made during that wait, which is Poisson-distributed with expectation lambda = z * q/p. The overall success probability, rearranged as in the whitepaper to avoid summing the distribution’s infinite tail, is:
z confirmations correspond to an expected wait of z x 10 minutes, the same as Bitcoin and roughly 40 times longer real-time exposure per confirmation than a 15-second chain - one Parallax confirmation embodies 40 times the expected work share of one 15-second-chain confirmation at equal network scale.
Evaluating for an attacker with 10% of the network:
and for an attacker with 30% of the network:
Solving for the confirmation depth that bounds the attacker’s success below 0.1%:
These reproduce the whitepaper’s figures exactly (as they must - the derivation is parameter-free), and the common “6 confirmations” heuristic corresponds to sub-0.1% risk against attackers controlling up to 12% of Parallax’s hashrate (at 12%, P = 0.00072; at 13%, P = 0.00115).
16.2 Block arrival and work expectation
Block discovery is a Poisson process with rate1/600 s^-1 at equilibrium. The probability that at least one block is found within t seconds is 1 - e^(-t/600):
With the XHash boundary
target = (2^256 - 1) // D, a single hash succeeds with probability (target + 1) / 2^256, so the expected number of hashimoto evaluations per block is 2^256 / (target + 1). Evaluated exactly in rational arithmetic, this deviates from D by less than one part in 10^66 for any realistic difficulty (verified at D = 10^3 and D = 10^12), so the estimator
2^256 - 1 as numerator (Section 11) costs nothing in work-accounting accuracy.
16.3 ASERT response analysis
ASERT (Section 13.2) is a proportional controller in log-target space: the target is an explicit exponential function of the chain’s cumulative schedule deviation,target = anchor_target * 2^((T - 600H)/172800) for drift T - 600H seconds. Its behavior under Parallax’s parameters:
Fixed-point exactness. The consensus code evaluates the exponential in 16.16 fixed point with a cubic approximation of 2^x on the fractional interval. Exhaustive evaluation over all 65,536 fractional inputs gives a maximum relative error of 0.0117% (worst case at x = 7057/65536), on top of an exponent quantization step of 2^-16 ≈ 0.0011%. Per-block target error from the approximation machinery is therefore bounded by about 1.2 parts in 10,000 and does not accumulate, because each block’s target is recomputed from the absolute schedule, not from the previous target.
Exact identities. Verified bit-for-bit against the consensus integer code:
- A chain exactly on schedule (
timeDelta = 600 * numBlocks) reproduces the anchor target exactly - the factor path yields precisely2^16and the shift path is idle. - A cumulative drift of exactly one half-life (±172,800 s) exactly doubles (or halves) the target: the fractional part is zero and the entire adjustment travels the error-free bit-shift path.
- A single block arriving 600 s late moves the target by ×1.002411 against a theoretical
2^(600/172800)= 1.002410.
tau * ln 10 = 159.5 h and 99% after 318.9 h, independent of the direction or (to first order) magnitude of the step. Simulating the exact consensus arithmetic with deterministic expected block times confirms the linearized prediction:
(The simulated 159.4 h for a hashrate halving matches the theoretical 159.5 h to 0.1%; upward steps complete in less wall-clock time because blocks arrive faster than 600 s throughout the transient.) Because scheduling is absolute, there is no steady-state error: once hashrate stabilizes, the expected spacing returns to exactly 600 s and any residual calendar drift stops growing, in contrast to window-based retargeting, which permanently forgets past drift.
16.4 Nakamoto-phase bounds
During the pre-ASERT phase (Section 13.1), a single retarget is clamped by the timespan bounds to the interval:17. Reference implementations and further reading
- C/C++ reference implementation, Python bindings, benchmarks: github.com/ParallaxProtocol/xhash
- Production Go implementation (consensus engine of the Parallax daemon): github.com/ParallaxProtocol/parallax -
kernel/xhash - Test vectors:
kernel/xhash/testdataand the test suites of both repositories (algorithm_test.go,xhash_test.go, and the C++test/directory) pin cache, dataset, and hashimoto outputs across implementations. - Background: Dagger-Hashimoto, Ethash, Lerner’s Strict Memory Hard Hashing Functions (2014), FIPS 202, the FNV specification, and the aserti3-2d specification.

