背景
CryptoNight最初是在2013年左右设计的,属于CryptoNote套件的一部分。
它的设计目标之一是通过采用以下方式,使其对目前的CPU比较友好:
- 本地AES加密
- 快速64位乘法器
- 适合精简版英特尔CPU上每核三级缓存的大小(约2MB)
更雄心勃勃的设计目标是使其在ASIC上无法有效计算。这个目标已经失败,因为“ASIC硬算法“能计算成功是不可避免的。高效的CryptoNight ASIC由Bitmain于2017年开发。
2014年,Monero将CryptoNight采用为自己的POW。在此之后,Monero略微改进了算法,故意破坏与已发布的ASIC-s的兼容性。目前,Monero实现了CryptoNight v2,这是对CryptoNight(v0,v1,v2)的第三次迭代。
目标是找到足够小的哈希
在基于哈希的PoW算法中,目标是找到足够小的哈希。
哈希只是一个整数(通常是一个非常大的整数)。大多数哈希函数生成256位哈希(0到2 ^ 256之间的整数)。这包括比特币的双SHA-256和Monero的CryptoNight。
矿机会随机调整输入数据,直至哈希符合指定的随机数。随机数(也是一个大整数)作为共识机制的一部分,由网络共同建立。如果哈希符合随机数,则仅认为PoW有效(已解决)。
因为哈希函数是单向的,所以足够小的哈希值是不可能通过分析计算出的。解决方案必须通过调整输入数据并反复重新计算才能得到。
矿工在输入方面有一些灵活性——最重要的是他们可以对随机数的值进行迭代。它们还具有将区块中包含交易组合在默克尔树(merkle)中,以及选择以什么样的方式组合的能力。
加密函数
CryptoNight基于:
- AES加密
- 5个哈希函数,全部都是NIST SHA-3的竞争函数:
- Keccak(主要的)
- BLAKE
- Groestl
- JH
- Skein
输入数据
在Monero中,哈希函数的输入是以下内容的连接:
- 序列化的区块头(大约46个字节;以varint格式表示)
- merkle树的根(32字节)
- 区块中包含的交易数(大约1-2个字节;以varint格式表示)
请参阅get_block_hashing_blob()函数以进一步探索。
算法
警告 本文试图让读者对CryptoNight算法有更深入的理解。有关实现的详细信息,请参阅CryptoNote Standard和Monero源代码。请参阅底部的参考资料。
概览
CryptoNight试图使内存访问成为性能的瓶颈(“内存硬度”,memory hardness)。它有三个步骤:
- 使用伪随机数据初始化大面积内存。此内存称为暂存器。
- 在暂存器上的伪随机(但确定性)地址执行大量读/写操作。
- 哈希计算整个暂存器以产生结果。
第1步:暂存器初始化
首先,使用Keccak-1600对输入数据进行哈希计算,生成200字节的伪随机数据(1600位== 200字节)。
使用AES-256加密,这200个字节成为生成更大的2MB宽的伪随机数据缓冲区的种子。
Keccak-1600哈希的前0-31字节用作AES密钥。
加密在128字节长的有效负载上执行,直到2MB准备就绪。第一个有效载荷是Keccak-1600的第66-191字节。下一个有效负载是先前有效负载的加密结果。
每个128字节的有效负载实际上加密了10次。
详细信息稍微有些细节,请参阅CryptoNote Standard中的“Scratchpad Initialization”。
第2步:内存硬循环
第二步是基本的简单重复524288次迭代。
每次计算迭代都会在在伪随机但确定的位置读取,并写回到暂存器。
关键的是,下一次迭代取决于先前迭代准备的状态,无法直接计算未来迭代的状态。
具体操作包括AES,XOR,8byte_mul,8byte_add这类对CPU友好的操作(在现代CPU上高度优化)。
这里的目标是使内存延迟成为填补潜在ASIC-s和通用CPU-s之间差距的瓶颈。
第3步:哈希计算
最后一步(简化)是:
- 使用上面的Keccak-1600输出
- 根据结果的2个低位选择哈希算法
- 0=BLAKE-256
- 1=Groestl-256
- 2=JH-256
- 3=Skein-256
- 使用所选函数进行哈希计算
得到的256位哈希是CryptoNight算法的最终输出。
Monero特定修改
CryptoNightv0
Monero社区引用的CryptoNight原始实现。
CryptoNightv1
查看源代码差异。
CryptoNightv2
CryptoNight v3 又名CryptoNightR
查看源代码差异。
批评
- CryptoNight哈希验证相对昂贵。这会因为给DoS-ing节点带来伪证明而增加风险。 可查看强非对称性的要求。
- 哈希函数是从头开始设计的,同行评审有限。 虽然CryptoNight由经过验证和同行评审的函数组成,但组合在一起的加密系统并不一定真的会足够安全。
- CryptoNight最终未能阻止ASIC-s。
- CryptoNight的复杂性阻碍了ASIC制造业的竞争。
CryptoNight工作证明仍然是门罗币最具争议的方面之一。
参考
- CryptoNight hash function 标准CryptoNote描述
- CryptoNight v2 source code
- 入口点是cn_slow_hash()函数。 手动删除多个体系结构的支持和优化应该有助于您了解实际代码。
- CryptoNote whitepaper 的平等工作量证明("Egalitarian Proof of Work")章节
- David Andersen博士撰写的First days of Monero mining
- 门罗币源码的一些 test vectors
本章内容由xi翻译制作,欢迎打赏作者。xi的门罗币钱包地址为:
49Zo7rnT3hKW8M8hBwD9AsbzisZsHPJYFbNB5e4ZeJymfWkG5twq4Kp5Vk1jxrkyev9CnGz7kW7JwbkpDAQxvsXkKwHYEAB