Go to file
2019-01-10 22:04:55 +01:00
doc Updated specification 2018-12-31 19:27:31 +01:00
src Random accesses - JIT compiler 2019-01-10 22:04:55 +01:00
tests ALU/FPU test: Fixed MSVC x86 build 2018-11-20 22:41:34 +01:00
.gitignore RandomX portable interpreter 2018-12-11 21:00:30 +01:00
LICENSE Initial commit 2018-11-01 00:34:52 +01:00
makefile Random accesses - JIT compiler 2019-01-10 22:04:55 +01:00
README.md Updated readme with performance data 2018-12-23 18:02:17 +01:00

RandomX

RandomX is an experimental proof of work (PoW) algorithm that uses random code execution.

Key features

  • Memory-hard (requires >4 GiB of memory)
  • CPU-friendly (especially for x86 and ARM architectures)
  • arguably ASIC-resistant
  • inefficient on GPUs
  • unusable for web-mining

Virtual machine

RandomX is intended to be run efficiently on a general-purpose CPU. The virtual machine (VM) which runs RandomX code attempts to simulate a generic CPU using the following set of components:

Imgur

Full description: vm.md.

Dataset

RandomX uses a 4 GiB read-only dataset. The dataset is constructed using a combination of the Argon2d hashing function, AES encryption/decryption and a random permutation. The dataset is regenerated every ~34 hours.

Full description: dataset.md.

Instruction set

RandomX uses a simple low-level language (instruction set), which was designed so that any random bitstring forms a valid program. Each RandomX instruction has a length of 128 bits.

Full description: isa.md.

Implementation

Proof-of-concept implementation is written in C++.

> bin/randomx --help
Usage: bin/randomx [OPTIONS]
Supported options:
        --help                  shows this message
        --compiled              use x86-64 JIT-compiled VM (default: interpreted VM)
        --lightClient           use 'light-client' mode (default: full dataset mode)
        --softAes               use software AES (default: x86 AES-NI)
        --threads T             use T threads (default: 1)
        --nonces N              run N nonces (default: 1000)
        --genAsm                generate x86 asm code for nonce N

Two RandomX virtual machines are implemented:

Interpreted VM

The interpreted VM is the reference implementation, which aims for maximum portability.

The VM has been tested for correctness on the following platforms:

  • Linux: x86-64, ARMv7 (32-bit), ARMv8 (64-bit)
  • Windows: x86, x86-64
  • MacOS: x86-64

The interpreted VM supports two modes: "full dataset" mode, which requires more than 4 GiB of virtual memory, and a "light-client" mode, which requires about 64 MiB of memory, but runs significantly slower because dataset blocks are created on the fly rather than simply fetched from memory.

Software AES implementation is available for CPUs which don't support AES-NI.

The following table lists the performance for Intel Core i5-3230M (Ivy Bridge) CPU using a single core on Windows 64-bit, compiled with Visual Studio 2017:

mode required memory AES initialization time [s] performance [programs/s]
light client 64 MiB software 1.0 9.2
light client 64 MiB AES-NI 1.0 16
full dataset 4 GiB software 54 40
full dataset 4 GiB AES-NI 26 40

JIT-compiled VM

A JIT compiler is available for x86-64 CPUs. This implementation shows the approximate performance that can be achieved using optimized mining software. The JIT compiler generates generic x86-64 code without any architecture-specific optimizations. Only "full dataset" mode is supported.

For optimal performance, an x86-64 CPU needs:

  • 32 KiB of L1 instruction cache per thread
  • 16 KiB of L1 data cache per thread
  • 240 KiB of L2 cache (exclusive) per thread

The following table lists the performance of AMD Ryzen 7 1700 (clock fixed at 3350 MHz, 1.05 Vcore, dual channel DDR4 2400 MHz) on Linux 64-bit (compiled with GCC 5.4.0).

Power consumption was measured for the whole system using a wall socket wattmeter (±1W). Table lists difference over idle power consumption. Prime95 (small/in-place FFT) and Cryptonight V2 power consumption are listed for comparison.

threads initialization time [s] performance [programs/s] power [W]
RandomX (interpreted) 1 27 52 16
RandomX (interpreted) 8 4.0 390 63
RandomX (interpreted) 16 3.5 620 74
RandomX (compiled) 1 27 407 17
RandomX (compiled) 2 14 810 26
RandomX (compiled) 4 7.3 1620 42
RandomX (compiled) 6 5.1 2410 56
RandomX (compiled) 8 4.0 3200 71
RandomX (compiled) 12 4.0 3670 82
RandomX (compiled) 16 3.5 4110 92
Cryptonight v2 8 - - 47
Prime95 8 - - 77
Prime95 16 - - 81

Proof of work

RandomX VM can be used for PoW using the following steps:

  1. Initialize the VM using a 256-bit hash of any data.
  2. Execute the RandomX program.
  3. Calculate blake2b(RegisterFile || t1ha2(Scratchpad))*

* blake2b is a cryptographic hash function, t1ha2 is a fast hashing function.

The above steps can be chained multiple times to prevent mining strategies that search for programs with particular properties (for example, without division).

Acknowledgements

The following people have contributed to the design of RandomX:

RandomX uses some source code from the following 3rd party repositories:

Donations

XMR:

4B9nWtGhZfAWsTxWujPDGoWfVpJvADxkxJJTmMQp3zk98n8PdLkEKXA5g7FEUjB8JPPHdP959WDWMem3FPDTK2JUU1UbVHo