前言

大约有一年时间没有写博客了,这段时间经历了很多事情,自己的生活也发生了很多以前没有想过的变化。一年间,主要的精力除了上班码代码之外,基本上都花在了投机市场当中。挣了不少钱,也亏了不少钱,但让我感到有些意思的,是这个 Chia 项目,想着如果不写一下的话,之后大约会忘记,于是就此执笔。

什么是 Chia ?

Chia 是一个新的区块链系统,是由 BitTorrent 之父 Bram Cohen 创立的。创立之初是觉得比特币太浪费电了(感觉这说法并不怎么靠谱),于是想搞个绿色数字货币,用硬盘来挖矿。 XCH 是 Chia 区块链系统中的代币,类比的话,大概相当于 XBT。对于 Chia 画下的大饼(智能合约、Chialisp等等)暂时按下不表,先说说他的挖矿,他的挖矿原理其实跟市面上的 FIL 挖矿不太一样,具体来说,分两步。

  • 第一步:计算 Plot 文件(俗称 P 盘),这个过程会使用一种特殊函数(Verifiable Delay Function),根据提供的 Farmer public key 与 Pool public key 预计算一批数字。在计算过程中,需要一块高速缓存盘用于存放临时计算数据,官方推荐 SSD 作为缓存盘。由于 SSD 具有 TBW (Terabytes Written,TB写入量) 的寿命,因此该过程实质上需要消耗大量 SSD。此外,对于 CPU 也有一定要求,CPU cache越大的话,速度也就越快。

  • 第二步:挖矿。与比特币挖矿类似,Chia 区块链的出块权利由应答 Challenge 成功的节点获得。但与比特币不一样的是,Challenge 的结果并不是由矿机计算出来的。取而代之的是,矿机会去扫描所有 Plot 文件,如果里面有能响应 Challenge 的 Plot 文件,则该 Plot 文件对应的 Public Key 获得该区块的打包权利与其对应的奖励。

Chia 的初心是想让大家用闲置的硬盘去 P 盘,并使用这些 Plot 文件去维护 Chia 区块链的稳定性。想法是好的,但在Chia 主网开启的两个月过程中,实际上算力还是逐渐向寡头集结的。截止至2021年5月14日,HPool 的 Chia 矿池算力已经达到2279PB,已经达到了全网的50%。

投机

Chia 的主网启动时间是 3 月 19 日, 我大约是 20 日知道的这个消息。 忘记是出于什么原因,总之就是想开始折腾,于是 21 号在研究了一番之后,往 OVHCloud 下了第一单测试机。

一、独立服务器挖矿

最开始的想法很单纯,当时主网算力增速较缓,在一番计算过后我发现,如果 Chia 币能维持在 50 美元的话,大概一个月便能收回成本。由于转账功能在 5 月 4 日才开放,本质上是在赌这个币是否能成功,于是我自己并没有花很多钱投入。最后是租了大概三台 P 盘机器,两台 48 T 的存储机器,花了大概一个月时间填满。这期间 SOLO + 矿池断断续续挖了大约 72 个币,使用的解决方案是笨拙的 rsync + bash。原理很简单,写一个监控程序将 P 盘机器中已经 P 完的文件实时传输到存储机的硬盘中,这中间为了加速传输的速度,还购买了 OVHCloud 的 Private bandwidth (虽然最后也好像没有快多少)。

二、云挖矿的尝试

由于瓶颈实际上是在 CPU 上,对于优化的方向,最开始我是想,如果能优化这个算法,提升多线程利用率就好了。在阅读完 chiapos 的源代码之后,感觉优化源代码这个方向的性价比实在太低,于是放弃,决定转向以量取胜,遂开始研究各大云厂商的产品。当时的想法是,Chia 挖矿原理无非是扫盘中的数据进行应答,并且扫盘不可能扫全部的文件内容,所以 OSS 是非常适合这项任务的,再加上云服务器的 CPU 比自己买实体矿机更是要划算许多。核心的思想也非常简单,使用 fuse 将 OSS mount 成系统的一个盘符即可。

AWS

(题外话:在我调研完 AWS 大约一个月后, AWS官方曾短暂放出过一篇 Chia on AWS 的教程,但之后估计因为合规问题删除了,原链接为:https://aws.amazon.com/cn/campaigns/chia-solution/ ,仍然能通过 archive.org 查看) 第一站当然是先调研了 AWS 的 S3 与自家 EC2 的契合度,在经过测试后发现,虽然 AWS 不愧是云服务商的中流砥柱,但价格上相对来说也比较贵,于是放弃。

GCP + GCS

那么谷歌又如何呢?经过研究之后发现,谷歌有一个抢占式实例的服务,这个抢占式实例跟 AWS on demand 差不多,都可以让你用更低(谷歌基本上是半价,AWS则是2折起)运行一个实例,但谷歌的这个实例没有办法自己报价,而且只能运行24小时,但这对我来说并没有什么影响。在前面的benchmark中我计算过,用最低配机器(N2-2vCPU,8G,1Local SSD)跑一个100 G的文件大约是8小时,在谷歌云最便宜的区域us-central1跑折算下来每T只要6.6美元。

存储方面,一开始,我曾经想使用 Google Drive,但后来发现 GD 并不支持随机读取,这就导致不可能使用 GD 进行 挖矿,因为如果你想读一个文件的中间部分,也需要把一个100G文件下载下来,这显然不现实。后来就直接选用了谷歌自家的 GCS ,GCS 的收费依据文件的存储时间分四个档次,存储越久的文件,价格越低,但与之相对的,读取文件的价格也越贵。刚开始我选择的是存储最久的 ARCHIVE,事实证明这并不是一个最佳选择,在经过成本核算后改成了 CODELINE。

技术方案中,选择了最稳妥的 gcsfuse,大致运行流程也很简单:

  • 新建一个虚拟机,把自动脚本调试完成,确保这个虚拟机一开机就开始进行 P 盘并上传到 GCS 指定 bucket 中,在这个阶段,我使用的是 rclone。有一点需要注意的是,实例默认创建时是没有 gcs 的权限的,如果遇到权限问题,不妨再检查一下虚拟机对 API 的权限设置。
  • 新建一个虚拟机模版,原型镜像就选上面那个虚拟机,然后把实例类型改为抢占式实例。
  • 新建一个实例组,然后拉满起飞。

由于实例组会帮我们自动维护实例的生命周期,所以如果一个文件完成上传,或者因为抢占式实例被关闭,也能自动重启打开,这就完成了 P 盘第一步。

挖矿方面,也有一些坑需要注意的。

第一个问题就是在bucket的文件超过 500 T 之后,可能经常会遇到超时的问题。

首先,需要把gcsfuse的http2关闭,这是第一个坑,但因为比较少人复现,gcsfuse的issue中并没有人解决这个问题,后来经过debug发现就是http2的问题。

在解决了 http2 后,扫盘也会间歇性的超时,这个问题无法避免,我一开始采用的方案是分 bucket 放文件,后来改了一下 gcsfuse,让每个被 mount 的 bucket 可以有不同的 offset,解决了问题。

最后在折腾了半个月后,我的最终解决方案是 docker + hpool的挖矿程序,每个文件夹独立分配一个docker的容器,然而这个时候 xch 已经从 每 PB 10个 xch 跌落到 0.33 个 xch 了。

假算力

// TODO