区块周期

前面 有详细介绍过 tripod内关于区块周期的概念。 通过定制区块周期,我们可以实现很多深度的功能, 比如共识算法。 下面我们以 pow共识 为例,代码原址在这里

  • 初始化区块链,构造创世区块
    func (p *Pow) InitChain() error {
        // 构造创世区块,并存入链中。
        chain := p.env.Chain
        gensisBlock := &types.CompactBlock{
            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 *CompactBlock) error {
    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 *CompactBlock) error {
    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(_ *CompactBlock) error {
	return nil
}

到此为止,一个基于 sha256的 pow共识机制 便完成了。