grin中pow算法-cuckoo cycle的lean算法简单分析

最近实习,接触了一个比较新颖的工作量证明算法:cuckoo-cycle,基本原理是在一个极大二分图中找到一个长度为proofsize的回路。

源码在这:https://github.com/tromp/cuckoo

算法介绍在网上也有:https://www.zuocoin.com/a/news/experience/2019/0401/32897.html

1.二分图的生成

这是一个基于图的pow算法,当然需要生成一个初始化二分图,cuckoo中使用siphash函数来生成一条边,通过随机数nonce,密钥对sipkeys,奇偶参数uorv来生成一条连接一个连接两个节点的边<odd, even>,这里每个边是连接一个奇数节点和一个偶数节点。

通过nonce从0枚举到NEDGES - 1,生成NEDGES个边。

2.剪枝

很简单,如果节点是环路中的一部分,那么它的度数必为2以上,那么度数为0和1的节点就可以进行剪枝。

3.图的搜索

生成二分图,其实可以发现,在sipkeys和nonce已知的情况下,可以默认二分图已经生成,我们只需要遍历即可。

4.寻找环路

如果发现新的edge加入后形成了一个环路,那么使用一个set<unode, vnode>来存储环路,一个递归寻找路径过程。

以上就是算法主要步骤。

讲讲算法细节吧。

我负责的是cuckoo中一个分支算法lean,使用cpu和内存来存储图的,做了一些多线程和压缩存储。

1.多线程:

lean中引入多线程来进行trim过程,每个线程负责一个block,每个block有64条边信息。

2.twice_set

twice_set使用了一个bitmap来进行压缩存储。之前说了,剪枝需要减去的是degree = 0/1的节点,degree > 1的节点可以不剪,那么通过degree把节点分为三种状态:0、1、>1,那么三种状态,可以使用2bit来表示,其中>1状态论文有说恒定为2。

根据高位是否为0来很快判断这个节点是否需要剪枝了。

那么这样子是不是就把节点存储大小压缩到了2 * NNODES bits了呢?

答案是No。

我们来看twice_set的大小:

上面默认PART_BITS = 0,atwice = uint32,可以看到ONCE_BITS大小为NEDGES >> PART_BITS,默认情况下等于NEDGES,那么TWICE_BITS = 2 * ONCE_BITS = NNODES  != 2 * NNODES。

因为这里在bitmap的基础上,进行奇偶复用

之前说了每个edge和node通过sipnode函数生成,也代表了edge和node有着映射关系:

只需要调整uorv参数,就可以得到一个边对应的两个节点,一个为奇一个为偶,并且每轮剪枝都是一轮奇一轮偶进行的,那么可以肯定同一个边的两个节点在一次剪枝中不会重复出现,每一轮剪枝存储该边对应的奇/偶节点,那么也就不难理解ONCE_BITS大小为什么是NEDGES >> PART_BITS了。 

3.shrinkingset 

同样也是使用bitmap来进行压缩存储,0/1代表这个边是否为叶节点的边,每个bit为0代表alive(非叶节点边),1代表non-alive(叶节点边)。这里使用的是一个uint64数组,上文多线程提到的block大小为64bit,也就是代表这个数组,一个block代表一个数组元素。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值