DFINITY区块链连载(五) - 随机灯塔示例

季宙栋季宙栋

前面几篇对DFINITY的概念做了一些原理说明,基于密码学的随机性构筑起了高效、安全的DFINITY网络,可能你还感觉有点云里雾里,没有关系,后面会伴随更加“干”的代码解析来进一步分析DFINITY网络。

作者:季宙栋、丛宏雷

核心关键词:随机灯塔、阈值接力

一、三层“横向扩展”结构及随机灯塔

横向扩展网络分为3层,自下而上:

1)存储层:数据存储在数据分片上,任意状态转换消息会传递到验证树

2)验证层:验证树是一个异步结构,随机灯塔选出的阈值组会去执行数据验证,验证树构成的叶子节点,使得验证塔逻辑上与Merkle树相似。

3)共识层:阈值接力机制产生随机数,选出的阈值组,保存验证塔的根状态数据,同时要通过随机灯塔选出验证树所属的组


二、随机灯塔示例代码解析

Random-beacon分析

随机灯塔是由阈值组之间的接力机制产生的,其中每个组都创建了一对BLS阈值签名密钥。 接力的下一个随机数依赖于前面一个随机数的唯一、确定的阈值组签名消息。 该机制被称为“阈值接力链”,是DFINITY网络的核心机制,随机灯塔是“阈值接力”机制应用于数据验证的主要功能。

代码地址:github.com/dfinity/rand


参数:

l:生成的block的数目,也是生成的随机数的数目

n:每个组中进程的数目

k:组的阈值

N:系统中总进程数目

m:阈值组的数目


Main.go 主函数

首先初始化一个区块链模拟器,再模拟器里面构建N个进程,然后分别加入到m个进程组中

然后在这个模拟器上依次调用Advance函数,每次都会生成出一个新的块,共调用L次

Func main()
Mysim
  = sim.NewBlockchainSimulator(seed, n, k, N, m)
For
  i = 0 : l
Mysim.Advance(1,
  false)



state/state.go

区块链中块的定义,

type State struct {
nodes
  map[common.Address]Node
groups
  map[common.Address]Group
sig
  bls.Signature
}



Sim/blockchain.go

Type BlockchainSimulator struct {
Proc
  []ProcessSimulator
Group
  []GroupSimulator
Grpmap
  map[common.Address]*GroupSimulator
Chain
  []state.State
}


1)初始化区块链模拟器

1. 创建N个进程

2. 创建m个组,然后随机挑选进程加入到这些组中

3. 创建一个新的状态,作为创始块

4. 把所有进程的信息加到创始块中(进程的公钥和对公钥的签名)

5. 把所有的组的信息加到创始块中(组中所有进程的地址,组公钥,组阈值)

6. 将创始块链接到区块链上

Func NewBlockchainSimulator (seed bls.Rand, groupSize, threshold,
  nProcesses, nGroups)
Sim.InitProcs(nProcesses)
Sim.InitGroups(nGroups)
Genesis
  = state.NewState()
For
  _, p := range sim.proc {
Genesis.AddNode(p.reginfo)
}
for
  _, g := range sim.group {
 genesis.AddGroup(g.reginfo)
}
sim.chain
  = append(sim.chain, genesis)


2)生成一个新的区块

1. 取出链上最后一个块

2. 将最后一个块的签名作为随机数,选出一个组

3. 组对随机数进行签名,生成一个新的签名

4. (网络结构没有变化),拷贝最后一个块,构造一个新块

5. 将新的签名保存到新区块中

6. 将新的块链接到区块链中

func (sim *BlockchainSimulator) Advance(n
  uint, verbose bool)
tip
  := sim.Tip()
a
  := tip.SelectedGroupAddress()
g
  := sim.grpmap[a]
sig
  := g.Sign(tip.Rand().Bytes())
newstate
  := tip
newstate.SetSignature(sig)
sim.chain
  = append(sim.chain, newstate)
sim.Advance(n-1,
  verbose)


3)选出新的阈值组

1. 采用块的签名作为随机数,对阈值组个数取模

2. 选出新的阈值组

func (s State) SelectedGroupAddress() common.Address {
	i := s.Rand().Modulo(len(s.groups))
	Return s.GroupAddressList()[i]


4)阈值组签名

1. 循环对阈值组中的每个进程

a) 这个进程对输入数据进行子签名,签名结果保存到sigmap中

2. 根据sigmap中各个进程的子签名,构建整个组的组签名(这个函数调用了c++实现的bls算法)

3. 完成了阈值组签名

Func (g GroupSimulator) Sign(msg
  []byte) bls.Signature
For
  _, p := range g.proclist {
sigmap[p.Address()]
  = p.SignForGroup(g.reginfo, msg)
}
sig1
  := bls.RecoverSignatureByMap(sigmap, g.reginfo.Threshold()) 从sigmap中取出thresh个签名,构造出群签名
return
  sig1
「这年头有搞技术的初心不容易」
还没有人赞赏,快来当第一个赞赏的人吧!
文章被以下专栏收录
还没有评论