Entropy简史
本来只是准备把过去一周的情况记录一下,但是今天延续了过去两天的糟糕状态,加上刚刚注册了APNet需要缓一缓,所以干脆把Entropy从古至今的变迁都过一遍吧。再不记就要开始忘了。
大概已经忘了很多了。虽然总是可以通过回顾投稿历史来帮助回忆,但是我不想承受观赏黑历史所带来的抑郁。
Entropy是第一个我独立设计解决方案的项目。它充分地说明了寻找一个靠谱的解决方案有多困难。至少对我来说。
22年下半年读了若干去中心化存储的社区文档以后,开始着手设计一个「更耐久(durable)」的存储系统。
ℒ首先提供的思路是极限压缩大法。为要存储的数据设计一道谜题,谜底就是要存储的数据,存储谜题的空间开销比存储数据要小。少存数据就可以更耐久。
显然最简单的谜题就是哈希值(不考虑碰撞的情况下),但是猜这个谜实在有点不太聪明的样子。
我设计了俩月有没有数据量更大但是更好猜的谜题。后来不记得具体怎么推导的了,但是最终的结论是这是在跟香农对着干。对于任何不确定的一位比特(或者等效一位比特),会让猜谜期望成本翻倍。所以只要存储数据达到了理论最大信息熵(比如压缩一下就可以非常接近),那么每进一步减少一比特存储空间就要用翻倍的计算来换。换不起一点。
ℒ认可了这个思路并不明智,提议说那可不可以针对存在一些作恶节点的场景,确保作恶节点不好好存数据不会导致数据丢失?
我说那简单,只要用喷泉码把所有人一起叫过来存数据就行了。
喷泉码是一种无纪律的擦除码,可以生成任意多互不相同的码字,然后在其中集齐任意k个就可以复原数据。
如果让所有人都来一人存一份码字,那么人越多一个数据占用的存储空间就越大,虽说总存储空间也大了就是了但是这样会使系统容量由存储空间最小的那个人的容量决定。所以不能所有人都存,只能选一些人来存。
我从Algorand那里抄来了选人算法。每个人拿到数据以后私底下摇个骰子,摇到自己就存。喷泉码可以轻易地保证每个人存的码字都不一样。
这样做有两个好处。一是数据不是谁想存谁就能存,必须摇到骰子才能存。这样如果有1/3的人汇报说自己存了,那么这一定不是1/3恶人在说瞎话实际上根本没人存的情况,而是至少大概有1/3乘以2/3(好人占比)的人存了(服从伯努利分布)。
另一方面,每个人私底下摇骰子所以没有人知道别人存了什么,从而不能专盯着存了某个数据的那伙人执行专门攻击。
一直到23年上半年应该都保持了这个思路,只是ℒ对如何选人稍作调整,改成了非均匀地集中在数据哈希值附近选人,从而可以用DHT加速,避免把每个数据推送到系统中的每一个人。我在此之上简化了修复数据的机制,大概是在23年下半年补上了。
这个阶段的评审意见主要是两方面:一是没听说过去中心化存储不知道它有啥用研究它干啥,二是觉得我们的设计太想当然。
前者主要是改进论文的写法。针对后者对设计的各处细节做提升,其中之一就是关于专门攻击。
长久以来我们对于存储系统的作恶模型的认识都很模糊。攻击者能不能在系统运行过程中,根据谁在干什么来挑选1/3的人干掉?
如果可以这样,那么任何把一份数据存在少于1/3的人头上的方案就都变得岌岌可危了。但是1/3的人是很多的,往那么多人头上扔数据很麻烦。
在上面的设计中我们让每个人自己偷偷摇骰子,避免攻击者统计到谁在存什么。但是数据是要在节点之间修复的,一修复谁提供了什么数据就很明显了。
23年下半年设计了双层编码。外层编码实际上就是加密,除了上传者没有人知道这是在存什么。连存数据的节点自己也不知道。
现在想来Swarm里做了一模一样的事。
评审意见懂了要去中心化存储干嘛,只是觉得我们的设计太想当然了。
如果实验可以说明这设计只是看着不靠谱实际上还是很好用的,那也许也能说服一些评审。坏就坏在实验很难做,做得又少又不精致,属实是雪上加霜。
24年初的投稿看起来没什么新的设计(对我还是开始浏览起了过往投稿),评审意见非常简短而沉闷,令人不知作何感想。
接下来我开始对设计做颠覆,因为我自己都觉得自己的设计在故弄玄虚,还漏洞百出。
抛骰子的概率函数是要根据系统的总人数来定的,这个要怎么知道?
在选人基于DHT以后,实际上抛骰子抛出来的人和DHT本来会选到的人已经相差无几。「入选证明」真的有用吗?如果没有入选证明,就算有额外的坏人跳出来说自己被选了,那些本应该会选中的人当中的好人还是会做他们该做的事,额外的坏人行为无法对他们产生影响。
除非本应该会选中的人就是一群坏人,但是我们又假设了坏人不能随意选择自己的身份,不然我们自己也处理不了。
所以我们能做到的,我们能保证的,纯用DHT做存储(也就是类似于Swarm)又有什么做不到的呢。都不用说Swarm,二十多年前的Glacier都差不多可以了。
通过加密的方式确实可以阻止攻击者了解谁在存什么,但是它还是可以轻易了解到哪些人在一起存东西。攻击者依然可以一窝端掉一份数据,即使它不知道自己攻击的是什么数据。这可以接受吗?
借助DHT找人存数据的做法会以相对变态的方式使用DHT(比如一次让它找800人出来),性能特征令人不安。
我对自己的工作,自己的设计缺乏信心。我不敢在论文中深入讨论,也不敢做很多种类的实验。实际上,实验中已经比基线多用了不知道多少倍的计算资源,足以吓退我的一切积极性。
首先在24年中设计了一个暴论版本的工作叫「我们一定要把每一份数据扔到系统中的每一个人头上才算安全」。理由是系统中的节点挂掉不是独立事件,一堆节点可以一起挂掉。所以安全模型不应该用概率模型来给各种排列组合的节点挂掉建模,而是直接穷举所有排列组合。
这个设计首先安全模型(被我描述得)很晦涩,然后过于严酷的安全模型导致解决方案看起来更不靠谱了。投的是短文,评审全都在说「就算你说的有道理的话,你这个东西也不能没有实验结果」。
24年下半年对设计进行了补充和改进,但是依然不够靠谱。这一轮的一个新的感悟是我对编码是完全的门外汉;都不用评审,我自己就能感觉到我对于编码能怎么用不能怎么用毫无直觉。
这一回合的设计大概就是「1/3的人是很多的」的回旋镖。把每个数据扔到每个人头上一点点。依靠节点的启动环节来完成数据修复,不再专门做修复,毕竟把所有节点叫到一起完成修复听着就很累。
但是把所有节点叫到一起存数据听着就不累了吗?加上对编码的生疏使用,想当然的冗余调整机制(听着不靠谱的同时还依赖于点人头),评审充满了欢快的气氛。
ℒ一直想要一个「比别的存储更耐久的存储」,因此就要有一个对比实验,在同样的条件下,Entropy就不丢数据,别的系统就丢数据。
别的系统真的丢数据吗?要是很容易就丢了那它们也不用做了。在随机拿掉节点的情况下别的系统也不丢数据。Entropy只有在精心挑选拿掉哪些节点的时候才能拉开差距。
首先这导致了这个实验很难做得好看,因为精心挑选节点会让别人瞬间丢掉所有数据,画一根直上直下的线有侮辱评审阅读能力的嫌疑。
其次Entropy为了应对精心挑选的节点攻击付出了很多代价(比如把数据往所有人头上扔),就算我们尽力说明性能尚可,也会让评审觉得「你没事吧」。
最后精心挑选的节点攻击可能会被认为是个很偏门的场景。从而进一步加剧了「你没事吧」的想法。
总的来说,别的存储系统在耐久方面做得已经挺好的了。号称比它们还好很容易哗众取宠。在我最近看了一系列别的存储以后更加这样觉得。
我很难复原上周末想到当前设计的具体心路历程了。早知道那篇日志就写具体点了。
根据我前一天的日志,我应该首先就注意到了Swarm存储用量不均匀的问题,并且前一晚就已经在这里集中注意力了。再之前我是倾向于做自发复制的设计的,从这时转为了「如果Swarm没有这个问题好像就无懈可击了」的想法。
然后想到了让容量大的节点加入多个子网。然后开始想要在DHT找人层面做文章。
然后来到工位开始查做负载均衡的相关工作,然后发现别人在用the power of two choices。
然后写了对Swarm的仿真。本来以为要凹一些特定的工况才能找到它空间利用率不佳的情况,结果一上来它就整了个个位数百分比出来。
空间利用率乍一看似乎跟耐久性不挨着,但是还是很容易讲出联系来的,比如说在系统规模下降时,原本存在多个节点上的数据「坍缩」到了一个节点上,不均匀的存储用量就有可能没有必要地把节点撑爆。
今天有点忙先不写了。