|
1 | 1 | ---
|
2 |
| -title: CryptoNight |
3 |
| -parent: Proof of Work |
| 2 | +layout: redirected |
| 3 | +sitemap: false |
| 4 | +permalink: /proof-of-work/cryptonight |
| 5 | +redirect_to: https://docs.getmonero.org/proof-of-work/cryptonight/ |
4 | 6 | ---
|
5 |
| - |
6 |
| -# CryptoNight |
7 |
| - |
8 |
| -> CryptoNight is a memory hard hash function |
9 |
| - |
10 |
| -## Background |
11 |
| - |
12 |
| -CryptoNight was originally designed around 2013 as part of the CryptoNote suite. |
13 |
| - |
14 |
| -One design goal was to make it very friendly for the off-the-shelf CPU-s, by employing: |
15 |
| - |
16 |
| -* native AES encryption |
17 |
| -* fast 64 bit multipliers |
18 |
| -* scratchpad fitting exactly the size of the per-core L3 cache on Intel CPUs (about 2MB) |
19 |
| - |
20 |
| -More ambitious design goal was to make it inefficiently computable on ASIC-s. |
21 |
| -This goal has since failed, as it inevitably happens with "ASIC hard" algorithms. |
22 |
| -Efficient CryptoNight ASIC was developed in 2017 by Bitmain. |
23 |
| - |
24 |
| -Monero inherited CryptoNight as its proof of work in 2014. |
25 |
| -Since then Monero slightly evolved the algorithm to intentionally break compatibility with released ASIC-s. Three used variants existed: Cryptonightv1, Cryptonightv2 and [Cryptonight-R](https://github.com/SChernykh/CryptonightR). |
26 |
| -**Monero no longer uses CryptoNight or any variant. Monero changed its mining algorithm to [RandomX](/proof-of-work/random-x) in November 2019.** |
27 |
| - |
28 |
| -## The goal is to find small-enough hash |
29 |
| - |
30 |
| -In hashing based PoW algorithms the goal is to find small-enough hash. |
31 |
| - |
32 |
| -Hash is simply an integer (normally, a very large integer). |
33 |
| -Most hashing functions result in 256-bit hashes (integers between 0 and 2^256). |
34 |
| -This includes Bitcoin's double-SHA-256 and Monero's CryptoNight. |
35 |
| - |
36 |
| -Miner randomly tweaks input data until the hash fits under specified threshold. |
37 |
| -The threshold (also a large integer) is established collectively by the network as part of the consensus mechanism. |
38 |
| -The PoW is only considered valid (solved) if hash fits under the threshold. |
39 |
| - |
40 |
| -Because hash functions are one-way, it is not possible to analytically calculate input data that would result in a small-enough hash. |
41 |
| -The solution must be brute-forced by tweaking the input data and recalculating the hash over and over again. |
42 |
| - |
43 |
| -Miners have a few areas of flexibility regarding input data - most importantly they can iterate with the nonce value. |
44 |
| -They also have a power over which transactions are included in the block and how they are put together in a merkle tree. |
45 |
| - |
46 |
| -## Cryptographic primitives |
47 |
| - |
48 |
| -CryptoNight is based on: |
49 |
| - |
50 |
| -* AES encryption |
51 |
| -* 5 hashing functions, all of which were finalists in NIST SHA-3 competition: |
52 |
| - * Keccak (the primary one) |
53 |
| - * BLAKE |
54 |
| - * Groestl |
55 |
| - * JH |
56 |
| - * Skein |
57 |
| - |
58 |
| -## Input data |
59 |
| - |
60 |
| -In Monero the input to hashing function is concatenation of: |
61 |
| - |
62 |
| -* serialized block header (around 46 bytes; subject to varint representation) |
63 |
| -* merkle tree root (32 bytes) |
64 |
| -* number of transactions included in the block (around 1-2 bytes; subject to varint representation) |
65 |
| - |
66 |
| -See [get_block_hashing_blob()](https://github.com/monero-project/monero/blob/master/src/cryptonote_basic/cryptonote_format_utils.cpp#L1078) function to dig further. |
67 |
| - |
68 |
| -## Algorithm |
69 |
| - |
70 |
| -{: .warning} |
71 |
| -> The article attempts to give reader a high-level understanding of the CryptoNight algorithm. |
72 |
| -> |
73 |
| -> For implementation details refer to CryptoNote Standard and Monero source code. |
74 |
| -> |
75 |
| -> See references at the bottom. |
76 |
| - |
77 |
| -### Overview |
78 |
| - |
79 |
| -CryptoNight attempts to make memory access a bottleneck for performance ("memory hardness"). It has three steps: |
80 |
| - |
81 |
| -1. Initialize large area of memory with pseudo-random data. This memory is known as the scratchpad. |
82 |
| -2. Perform numerous read/write operations at pseudo-random (but deterministic) addresses on the scratchpad. |
83 |
| -3. Hash the entire scratchpad to produce the resulting value. |
84 |
| - |
85 |
| -### Step 1: scratchpad initialization |
86 |
| - |
87 |
| -Firstly, the input data is hashed with Keccak-1600. This results in 200 bytes of pseudorandom data (1600 bits == 200 bytes). |
88 |
| - |
89 |
| -These 200 bytes become a seed to generate a larger, 2MB-wide buffer of pseudorandom data, |
90 |
| -by applying AES-256 encryption. |
91 |
| - |
92 |
| -The first 0..31 bytes of Keccak-1600 hash are used as AES key. |
93 |
| - |
94 |
| -The encryption is performed on 128 bytes-long payloads until 2MB is ready. |
95 |
| -The first payload are Keccak-1600 bytes 66..191. |
96 |
| -The next payload is encryption result of the previous payload. |
97 |
| - |
98 |
| -Each 128-byte payload is actually encrypted 10 times. |
99 |
| - |
100 |
| -The details are a bit more nuanced, see "Scratchpad Initialization" in [CryptoNote Standard](https://cryptonote.org/cns/cns008.txt). |
101 |
| - |
102 |
| -### Step 2: memory-hard loop |
103 |
| - |
104 |
| -The second step is basically 524288 iterations of a simple stateful algorithm. |
105 |
| - |
106 |
| -Each algorithm iteration reads from and writes back to the scratchpad, |
107 |
| -at pseudorandom-but-deterministic locations. |
108 |
| - |
109 |
| -Critically, next iteration depends on the state prepared by previous iterations. |
110 |
| -It is not possible to directly calculate state of future iterations. |
111 |
| - |
112 |
| -The specific operations include AES, XOR, 8byte_mul, 8byte_add - operations that are CPU-friendly (highly optimized on modern CPU-s). |
113 |
| - |
114 |
| -The goal here is to make memory latency the bottleneck in attempt to close the gap between potential ASIC-s and general purpose CPU-s. |
115 |
| - |
116 |
| -### Step 3: hashing |
117 |
| - |
118 |
| -The final step (simplifying) is to: |
119 |
| - |
120 |
| -* combine original Keccak-1600 output with the whole scratchpad |
121 |
| -* pick the hashing algorithm based on 2 low-order bits of the result |
122 |
| - * 0=BLAKE-256 |
123 |
| - * 1=Groestl-256 |
124 |
| - * 2=JH-256 |
125 |
| - * 3=Skein-256 |
126 |
| -* hash the result with selected function |
127 |
| - |
128 |
| -The resulting 256-bit hash is the final output of CryptoNight algorithm. |
129 |
| - |
130 |
| -## Monero specific modifications |
131 |
| - |
132 |
| -### CryptoNight v0 |
133 |
| - |
134 |
| -This is how Monero community refers to original implementation of CryptoNight. |
135 |
| - |
136 |
| -### CryptoNight v1 |
137 |
| - |
138 |
| -See the [source code diff](https://github.com/monero-project/monero/pull/3253/files). |
139 |
| - |
140 |
| -### CryptoNight v2 |
141 |
| - |
142 |
| -See the [rationale](https://github.com/SChernykh/xmr-stak-cpu/blob/master/README.md) and the [source code diff](https://github.com/monero-project/monero/commit/5fd83c13fbf8dc304909345e60a853c15b0de1e5#diff-7000dc02c792439471da62856f839d62). |
143 |
| - |
144 |
| -### CryptoNight v3 aka CryptoNightR |
145 |
| - |
146 |
| -See the [rationale](https://github.com/monero-project/monero/pull/5126) and the [source code diff](https://github.com/monero-project/monero/pull/5126/files). |
147 |
| - |
148 |
| -## Critique |
149 |
| - |
150 |
| -* CryptoNight hash is relatively expensive to verify. This poses a risk of DoS-ing nodes with incorrect proofs to process. See [strong asymmetry](/proof-of-work/what-is-pow/#strong-asymmetry) requirement. |
151 |
| -* The hash function was designed from scratch with limited peer review. While CryptoNight is composed of proven and peer-reviewed primitives, combining secure primitives doesn't necessarily result in a secure cryptosystem. |
152 |
| -* CryptoNight ultimately failed to prevent ASIC-s. |
153 |
| -* Complexity of CryptoNight kills competition in ASIC manufacturing. |
154 |
| - |
155 |
| -CryptoNight proof of work remains one of the most controversial aspect of Monero. |
156 |
| - |
157 |
| -## Reference |
158 |
| - |
159 |
| -* [CryptoNight hash function](https://cryptonote.org/cns/cns008.txt) description in the CryptoNote Standard |
160 |
| -* [CryptoNight v2 source code](https://github.com/monero-project/monero/blob/master/src/crypto/slow-hash.c) |
161 |
| - * The entry point is `cn_slow_hash()` function. Manually removing support and optimizations for multiple architectures should help you understand the actual code. |
162 |
| -* "Egalitarian Proof of Work" chapter in [CryptoNote whitepaper](https://downloads.getmonero.org/whitepaper_annotated.pdf) |
163 |
| -* [First days of Monero mining](https://da-data.blogspot.com/2014/08/minting-money-with-monero-and-cpu.html) by dr David Andersen |
164 |
| -* Some [test vectors](https://github.com/monero-project/monero/tree/master/tests/hash) in Monero source code |
0 commit comments