Skip to main content
XHash is the proof-of-work function of the Parallax protocol. It is a memory-hard algorithm in the Dagger-Hashimoto lineage, derived from Ethash but re-specified with standardized cryptography, a corrected data-aggregation function, a network-unique seed chain, and epoch parameters matched to Parallax’s 10-minute block interval. The combined effect is that every internal data structure of XHash (cache, dataset, and mix) is bit-for-bit incompatible with Ethash, rendering existing Ethash ASICs and shared DAG infrastructure useless against the Parallax network while preserving the memory-hard properties that keep commodity GPUs competitive. This page is the normative specification of the algorithm. Two implementations exist and are kept in strict agreement with it:
  • ParallaxProtocol/xhash - the standalone C/C++ reference implementation (CMake build, Python bindings, and an xhash-bench microbenchmark 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 in algorithm.go, seal verification in consensus.go, and difficulty adjustment in difficulty.go and asert.go.
Readers new to memory-hard proof-of-work should read the Dagger-Hashimoto and Ethash pages first; this specification is self-contained but assumes familiarity with the general construction.

1. Design goals

XHash was designed under four constraints:
  1. 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.
  2. 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.
  3. 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.
  4. 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 .be suffix).
  • A word is a 32-bit unsigned integer. A node (or item) is 64 bytes, i.e. 16 words.
  • sha3_256 and sha3_512 denote FIPS 202 SHA3-256 and SHA3-512 (standard padding 0x06). keccak256 denotes legacy Keccak-256 (padding 0x01) 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 from i to j.
  • 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

The chain magic is the ASCII string 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:
Both implementations ship precomputed lookup tables for the first 2,048 epochs (about 28 years of chain time) and fall back to the derivation above beyond that; see 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:
  1. 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.
  2. 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.
The single exception is the seal hash of the block header (Section 10), which uses legacy Keccak-256. This is intentional: Parallax block and transaction hashing follows the Ethereum wire conventions throughout the protocol, and the seal hash is a protocol-layer quantity, not part of the PoW core. The PoW core treats it as an opaque 32-byte input.

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:
Formally, with s_0 = 0^32:
Injecting the 9-byte magic into every iteration makes the entire seed chain, from epoch 1 onward, unique to Parallax. An Ethash-family chain (which computes 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:
where 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:
Two properties matter for the construction:
  • Non-associativity and non-linearity in the state. Like Ethash’s variant, fnv1 is 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.
Vectors of words are combined elementwise:
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 aggregating DATASET_PARENTS = 256 pseudorandomly selected cache nodes:
The parent index depends on the evolving mix, so the 256 cache reads per node are sequentially dependent: a device cannot know read 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:
Design notes:
  • 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 i depends on the mix produced by iteration i-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 makes result a statistically unbiased 256-bit value, and it creates a cheap outer PoW - a peer can hash s || cmix and 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-byte seal_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 difficulty D when the hashimoto result, interpreted as a big-endian 256-bit integer, satisfies:
XHash defines the boundary as (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:
  1. Recompute seal_hash from the received header (Section 10).
  2. Evaluate hashimoto. A full verifier with the current DAG uses hashimoto_full; a light verifier uses hashimoto_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.
  3. Reject with invalid mix digest unless the computed mix_digest equals the header’s mixHash. This check ensures the miner actually performed the memory-hard inner loop and lets verifiers reject forgeries before the target comparison.
  4. Reject with invalid proof-of-work unless result <= (2**256 - 1) // difficulty.
The daemon verifies with the cache by default and uses the full DAG only when one is already generated (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-configured asertActivationHeight (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 carries epoch_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:
Between boundaries difficulty is constant. Because 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:
where, evaluating from parent block 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.
The exponential is evaluated in integer-only fixed-point arithmetic with radix 2^16, using the cubic polynomial approximation of 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 outer sha3_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 in asert.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
The probability of catching up falls geometrically in 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:
This analysis counts blocks, not seconds, so it applies to Parallax exactly as to Bitcoin; only the wall-clock interpretation changes. With Parallax’s 600-second spacing, 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 rate 1/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
holds without correction terms, and the choice of 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 precisely 2^16 and 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.
Step response. Linearizing the controller: after a sudden hashrate change, the spacing error decays exponentially with time constant
giving 90% adjustment after 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:
verified over the full clamp range (an instant interval clamps to ×4, an arbitrarily slow one to ×0.25, an on-schedule one to ×1). Difficulty can therefore change by at most a factor of 4 per 2,016 blocks (14 days) before activation height 17,560, after which the ASERT dynamics of Section 16.3 govern.

17. Reference implementations and further reading