区块周期
前面 有详细介绍过 tripod
内关于区块周期的概念。 通过定制区块周期,我们可以实现很多深度的功能, 比如共识算法。 下面我们以
pow共识 为例,代码原址在这里 。
- 初始化区块链,构造创世区块
func (p *Pow) InitChain() {
// 构造创世区块,并存入链中。
chain := p.env.Chain
gensisBlock := &types.Block{
Header: &types.Header{},
}
err := chain.SetGenesis(gensisBlock)
if err != nil {
return err
}
// 启动一个线程来实时拉取P2P网络中来自于其他节点的数据
go func() {
for {
msg, err := p.env.P2pNetwork.SubP2P(StartBlockTopic)
if err != nil {
logrus.Error("subscribe message from P2P error: ", err)
continue
}
p.msgChan <- msg
}
}()
return nil
}
- 区块开始时,构造区块
func (p *Pow) StartBlock(block *Block) {
pool := p.env.Pool
// 在本地节点出块之前如果收到来自其他节点的区块,验证合法之后将跳过挖矿,直接将该区块存入链中。
// 如果没有或者区块不合法,则本地节点开始挖矿。
if p.UseBlocksFromP2P(block) {
logrus.Infof("--------USE P2P block(%s)", block.Hash.String())
return nil
}
// 从交易池中打包交易出来
txns, err := pool.Pack(p.packLimit)
if err != nil {
return err
}
......
//开始挖矿:计算哈希
nonce, hash, err := spow.Run(block, p.target, p.targetBits)
if err != nil {
return err
}
......
// 挖到矿以后,将该区块广播到P2P网络中去。
return p.env.P2pNetwork.PubP2P(StartBlockTopic, rawBlockByt)
}
- 区块结束时
func (*Pow) EndBlock(block *Block) {
chain := p.env.Chain
pool := p.env.Pool
// 执行区块中的交易
err := p.env.Execute(block)
if err != nil {
return err
}
// 将区块存入链中持久化
err = chain.AppendBlock(block)
if err != nil {
return err
}
return pool.Reset(block)
}
- 最终共识,敲定区块:
由于 pow共识 一般是不需要最终共识的这个敲定阶段的, 因为他们有最长子链或者最重子链等证明算力的方式。 所以这里我们
FinalizeBlock()
不用实现。
func (*Pow) FinalizeBlock(_ *Block) {
return nil
}
到此为止,一个基于 sha256的 pow共识机制 便完成了。