BI_EXTRA 附加块实质上是还未确定的主块候补(不知道理解的对不对)
/* if not read from storage and timestamp is ...ffff and last field is nonce then the block is extra */
//如果不是从持久化中读取出来的话 说明是新建的或者接收到的 且时间是 ...ffff 即是epoch中最后的一个时间戳 最后一个字段是输入签名类型 用来填写nonce 都符合生成主块的条件
if (!g_light_mode && (transportHeader & (sizeof(struct xdag_block) - 1))
&& (tmpNodeBlock.time & (MAIN_CHAIN_PERIOD - 1)) == (MAIN_CHAIN_PERIOD - 1)
&& (signinmask & (1 << (XDAG_BLOCK_FIELDS - 1)))) {
tmpNodeBlock.flags |= BI_EXTRA;
}
orphan链(孤块池 orphan链1为孤块链 orphan链2为附加块链)
1.矿池主块同步
主块传输 (涉及加密 解密)
主块头字段transport_header为ttl用于判断是否需要广播
添加主块(加载进内存以及持久化)
区块加载到内存的过程
-
检验区块是否存在
-
检验区块时间是否符合标准
-
区块输出签名个数是不是偶数
-
区块所有链接块(输入输出)是否存在 (不存在则去请求区块)
-
利用区块提供公钥检查输入输出签名以及输入是否合法(交易块)
-
计算区块难度
-
持久化(已持久化的不需要 附加块不需要)
-
更新最新主链
疑惑:每次从磁盘加载的时候还需要做各种验证处理的工作 而且必须从起始到尾的加载 是不是这样影响了整个的加载速度
第7、8步的详细内容
-
如果是附加块或者如果是从本地磁盘加载的 则不持久化 如果都不是 持久化进磁盘
-
如果当前orphan 链2中附加块个数过多 需重用-Reuse(貌似是直接将最旧的附加块取消了 其链接的区块也视为无效 不会从orphan链中取出 可以供后续链接用)
-
根据该区块难度更新当前主链主块
-
处理该区块的链接块
-
非附加块情况:在orphan链中(存储未被引用的区块)移除该区块链接的所有区块 (如果链接块中有附加块 则移除附加块 持久化进磁盘 不再是附加块 并把附加块链接的区块也从orphan链中移除 )
-
附加块情况:不做处理(即后续创建区块可以引用该区块链接的区块)
-
-
该区块加入orphan链中(非附加块加入orphan链1,附加块加入orphan链2)
主块难度根据hash大小判定 主块是整个epoch中难度最大的区块
难度计算
- (1) 如果链接块跟自身不是同一个epoch:区块难度=链接块+自身难度
- (2)如果链接块跟自身是同一个epoch:递归链接块的最大难度链接块直到不与自身epoch相同的区块 用(1)获得区块难度 并于一开始与自己同个epoch的链接块的难度进行比较 选取最大值
区块计算与每个链接块获得的难度值并选取最大难度作为自身难度值,最大难度链接块为使自身难度达到最大的链接块
附加块在orphan链2中的两种移除方法
- normal
移除自身 持久化进磁盘 设置自身不再是附加块 同时移除orphan链中其链接的所有区块
- reuse
仅移除自身 设置自身不再是附加块
reuse用在附加块一直不被新的区块链接的情况且当前附加块数量超出最大限制(65536) 时就将附加块从orphan链2中移除 同时在红黑树中也移除
应该是指取消该区块吧 其中区块链接的所有区块可以重新利用 因为没有从orphan链中移除
[疑惑]orphan链2中附加块是被谁链接的 没人从orphan链2中取出区块 感觉只有当被当作主块链接时才有可能从orphan链2中取出
2.区块链接
构建主块见证块的时候从orphan链中取出一定数量的区块(主块最多只能链接11个区块,见证块最多只能链接12个区块,因为主块最后一个字段需要填入输入签名类型的nonce值)
image-20191116212947725.png
构建交易块的时候直接链接输入输出
主链
存放每个epoch难度最大的区块
orphan链1
每添加一个新的非附加块进入本地,会将其放入orphan链1中,同时将其链接的区块从orphan链1中删除,并将它们标记为BI_REF,表明这些区块有人链接,同时新增的区块还没被人链接。
orphan链2
orphan链2保存的是BI_EXTRA类型的区块
Block_queue
block_queue保存的是矿池从矿工接收到的区块以及矿池支付给矿工的交易块,随后通过一个pool_block_thread线程从队列里取出区块持久化并发送给其他矿池
Sync_queue
接收其他矿池发送过来的区块,如果添加到本地成功,从同步队列中移除,否则添加到待同步队列中
区块标志
enum bi_flags {
BI_MAIN = 0x01, //setmain设置区块为主块时标志该位
BI_MAIN_CHAIN = 0x02, //跟BI_MAIN差不多 不过BI_MAIN是确定的 BI_MAIN_CHAIN是还未确定的 随着难度更大的区块添加不断更新
BI_APPLIED = 0x04, //区块被应用apply后可能会标志该标识位(不一定会标记的原因是区块可能存在双花交易等问题不过还是会被指向)
BI_MAIN_REF = 0x08, //区块应用apply过后会置该标识位
BI_REF = 0x10, //从孤块链中移除 即有区块链接孤块的时候 将孤块置为BI_REF
BI_OURS = 0x20, //添加区块时如果该区块的签名可以用自身的公钥解 则说明该区块是自己的区块
BI_EXTRA = 0x40, //标记符合主块条件的区块 即时间戳是epoch中最后的时间 同时存在最后一个输入签名字段用作nonce
BI_REMARK = 0x80 //这个不理解
};
矿池分发任务
发送两个任务字段taskfield
-
第一个字段
包含主块除去最后两个字段的区块信息的ctx的状态state
-
第二个字段
主块倒数第二个字段的数据
矿工计算并发送share
矿工接收到taskfield1 与 taskfield2
利用taskfield1恢复ctx 添加taskfield2的数据
最后一个字段前192bit填入矿工自身地址 后续64bit作为nonce 不断计算整个区块的最小hash 并将对应的nonce填入64bit中
image-20191116211546754.png最后将最后一个字段即 192bit address + 64bit nonce发送给矿池
网友评论