- Block结构调整
参考paper当中定义,在文件 src\primitives\block.h 中,将CBlockHeader和CBlock类调整如下:
CBlockHeader当中增加 h’和digest(F)字段,以及相应的初始化以及序列化修改。
![](https://i-blog.csdnimg.cn/blog_migrate/6679f397601d2695b1d2d49f865a7ef3.png)
CBlock当中添加 vector表示F (fruits set),只包含了Header信息。
![](https://i-blog.csdnimg.cn/blog_migrate/34ab65506d35e5713412729c7d906ef3.png)
可以看出,Fruit的结构与Block结构是一样的,使用了相同的CBlockHeader。
- Fruit Memory Pool
参考交易内存池CTxMemPool定义了类CFrtMemPool用于fruit内存池,具体定义见文件 src\frtmempool.h,其中,用于fruit的存储,使用了一个boost的多关键字索引容器,具体定义如下:
![](https://i-blog.csdnimg.cn/blog_migrate/b29d50bf5e2c2103c04d0ff0b50261c8.png)
MapFrt容器用于保存fruit,按照frtid排序(也是fruit的hash),可以通过多种方式进行查找,分别是:非唯一索引指向block的高度(pointer_height_fruit)、非唯一索引收到fruit的时间(entry_time_fruit)和唯一索引fruit的hash值(minint_hash_fruit),每个fruit的结构为 CFrtMemPoolEntry,也定义在frtmempool.h当中。
同时在main.cpp当中定义了fruitpool的全局变量:
![](https://i-blog.csdnimg.cn/blog_migrate/2958dcd7aadacf619aab3fa019988556.png)
- 数据接收
与标准bitcoin程序一样,通过注册的ProcessMessages函数进行数据的接收与发送,但是在消息类型中增加了对fruit的支持。具体定义在src\protocol.cpp当中:
![](https://i-blog.csdnimg.cn/blog_migrate/790a8cb4bfb27319c91b233cad00f7c6.png)
关于Fruit的消息处理,具体代码见src\main.cpp的ProcessMessage函数:
![](https://i-blog.csdnimg.cn/blog_migrate/4f606062271cc5acb3b542983a07feef.png)
对于该fruit,调用AcceptToFruitMemoryPool来进行处理:
- 调用CheckFruit判断该fruit的difficulty是否满足
- 判断frtmempool当中是否已经存在
- 判断该fruit指向的block是否是足够近的block,即是否满足freshness要求
![](https://i-blog.csdnimg.cn/blog_migrate/447ddb34084c297c39dc9a139427629d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/03140e82d2fcc38d84c4f633bf78d138.png)
在判断freshness的时候,8个之内block满足要求:
![](https://i-blog.csdnimg.cn/blog_migrate/9bfc8179740e59c00bafecbd951aa2d3.png)
- 判断该fruit是否已经被之前的block打包过了,全局定义的frtmempool_used容器中包含了已经被用过的fruit的信息。
- 如果以上都满足要求,将其放入frtmempool当中,便于mining模块使用。
- 挖矿流程
挖矿具体代码见源文件 src\rpc\mining.cpp和src\miner.cpp。
调用generateBlocks产生新的block,具体流程如下:
- 创建新的block,通过CreateNewBlock方法
![](https://i-blog.csdnimg.cn/blog_migrate/d0933b444a3c0a1573f513a7f3b279da.png)
在创建block时,基本参照bitcoin流程,初始化BlockHeader,计算difficulty获取需要计算的0个位数,并通过addFrts将之前收到的fruits放进来
![](https://i-blog.csdnimg.cn/blog_migrate/69595eaf58ecc27b3ab4966190df1a8f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2906531fe4f7e381d4dc9bb50fbf01a4.png)
- 基于block的diffculty计算fruit的difficulty,可以看出这里直接将当前block的difficulty降了100倍作为fruit的difficulty:
![](https://i-blog.csdnimg.cn/blog_migrate/009f11a2f640501dd284e593068d6dfa.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3b6c4de4ab2aaf9ac29d0f197a621dca.png)
- 开始挖矿流程,核心流程如下所示,将nNonce递增,循环计算block的hash,如果满足block的要求,则block挖成功,如果不成功,再判断是否满足fruit的要求。
![](https://i-blog.csdnimg.cn/blog_migrate/958d641624e02ed49ef92ec2a5e265f1.png)
- 挖到新的block后,调用ProcessNewBlock进行块的处理,处理中注意方法AcceptBlock:接受该block并保持到本地,并将该block中包含的fruit信息从frtmempool移至frtmempool_used当中。
同时,继续调用方法ActivateBestChain方法,在将该block添加到chain上时,做出Mining的激励。
- Mining的激励
与标准bitcoin的激励方式不同,在调用CreateNewBlock创建新的块时,并没有构造创币交易,即coinbase交易,已经注释掉:
![](https://i-blog.csdnimg.cn/blog_migrate/62da0895e2f9993fb039801d75586111.png)
而当挖到block以后,调用ProcessNewBlock将该block添加到chain上时,包含了对于Mining的奖励生成。
调用顺序为:
ProcessNewBlock->ActiveBestChain->ActivateBestChainStep->ConnectTip
->ConnectBlock->CalculateRewardDistribution
最后生成的所以激励交易txChanged,再进行进一步的确认:
![](https://i-blog.csdnimg.cn/blog_migrate/a930ad83d25a80d16d701e712618cb9b.png)
下面具体分析激励分配部分,具体代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/b856a5bd39edaa9bde1b7fa7f4ec4938.png)
首先调用IsTimeToDistributeReward函数,判断是否需要分配,按照设计,它这里每16个块才进行一次激励分配,而且是已经确认的(8个block之前的16个block进行激励分配):
![](https://i-blog.csdnimg.cn/blog_migrate/bdfd28fbc7c47a7187733aa9def08e59.png)
按照注释,分配原则如下:
calculate reward distribution of this episode
:
total reward S = nfees + GetBlockSubsidy()for each block
let f[i] = number of fruits collected by block i, F = sum f[i]
then for each fruit collected by block j,
its collector get co =(1 - tax + RewardFractionDiff(i))*(1 / F)*S,
its creator get cr = (1 / F) * S – co
additionally:
creator of block i get FEE_FRACTION_C1 * fee[i] for reward
RewardFractionDiff(i) =
REWARD_DIFF_FRACTION_C3 * (1 - (i - 1) / (k - 1))
|
即:
要分配总奖励:S=所有矿工费 nfees + 这个周期所有block应得奖励总和
f[i] 表示包含于block i中fruits的个数, F = sum f[i],即周期内所有fruit个数
对于每个fruits j,包含它的block 可以得到奖励:
Co = (1 – tax + RewardFractionDiff(i)) * (1 / F) * S
挖到fruit的可以得到奖励:
Cr = (1 / F ) * s – Co
另外,挖到块block i还能得到奖励
FEE_FRACTION_C1 * fee[i]
其中参数
RewardFractionDiff(i) = REWARD_DIFF_FRACTION_C3 * ( 1 – i – 1) / (k – 1)。
根据代码, FEE_FRACTION_C1为1 / 100, REWARD_DIFF_FRACTION_C3为1/100。
具体代码可以自己分析:
![](https://i-blog.csdnimg.cn/blog_migrate/a81e9827a2a525f2b1aa853e83184e3a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/5b1d5bf04707ce77a21ff9204ae0408e.png)