github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/consensus/dpos/dpos.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:32</date>
    10  //</624342611179606016>
    11  
    12  package dpos
    13  
    14  import (
    15  	"bytes"
    16  	"encoding/binary"
    17  	"errors"
    18  	"fmt"
    19  	"math/big"
    20  	"sync"
    21  	"time"
    22  
    23  	"github.com/ethereum/go-ethereum/accounts"
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/consensus"
    26  	"github.com/ethereum/go-ethereum/consensus/misc"
    27  	"github.com/ethereum/go-ethereum/core/state"
    28  	"github.com/ethereum/go-ethereum/core/types"
    29  	"github.com/ethereum/go-ethereum/crypto"
    30  	"github.com/ethereum/go-ethereum/crypto/sha3"
    31  	"github.com/ethereum/go-ethereum/ethdb"
    32  	"github.com/ethereum/go-ethereum/log"
    33  	"github.com/ethereum/go-ethereum/params"
    34  	"github.com/ethereum/go-ethereum/rlp"
    35  	"github.com/ethereum/go-ethereum/rpc"
    36  	"github.com/ethereum/go-ethereum/trie"
    37  	lru "github.com/hashicorp/golang-lru"
    38  )
    39  
    40  
    41  const (
    42  extraVanity        = 32   //固定为签名者虚荣保留的额外数据前缀字节数
    43  extraSeal          = 65   //固定为签名者密封保留的额外数据后缀字节数
    44  inmemorySignatures = 4096 //要保存在内存中的最近块签名数
    45  
    46  //blockinterval=int64(10)//出块间隔
    47  //epochinterval=int64(86400)//选举周期间隔24*60*60 s
    48  //最大验证大小=21
    49  //
    50  //conensusize=15//maxvalidatorsize*2/3+1
    51  blockInterval    = int64(10)  	//附带条件
    52  epochInterval    = int64(60)  //选举周间隔24*60*60 s
    53  	maxValidatorSize = 3
    54  safeSize         =  2	//maxvalidator大小*2/3+1
    55  consensusSize    =  2	//maxvalidator大小*2/3+1
    56  )
    57  
    58  
    59  
    60  var (
    61  	big0  = big.NewInt(0)
    62  	big8  = big.NewInt(8)
    63  	big32 = big.NewInt(32)
    64  
    65  frontierBlockReward  *big.Int = big.NewInt(5e+18) //
    66  byzantiumBlockReward *big.Int = big.NewInt(3e+18) //从拜占庭向上成功开采一个区块,在魏城获得区块奖励
    67  
    68  	timeOfFirstBlock = int64(0)
    69  
    70  	confirmedBlockHead = []byte("confirmed-block-head")
    71  )
    72  
    73  var (
    74  //当请求块的签名者列表时,返回errunknownblock。
    75  //这不是本地区块链的一部分。
    76  	errUnknownBlock = errors.New("unknown block")
    77  //如果块的额外数据节短于
    78  //32字节,这是存储签名者虚荣所必需的。
    79  	errMissingVanity = errors.New("extra-data 32 byte vanity prefix missing")
    80  //如果块的额外数据节似乎不存在,则返回errmissingsignature
    81  //包含65字节的secp256k1签名。
    82  	errMissingSignature = errors.New("extra-data 65 byte suffix signature missing")
    83  //如果块的mix digest为非零,则返回errInvalidMixDigest。
    84  	errInvalidMixDigest = errors.New("non-zero mix digest")
    85  //如果块包含非空的叔叔列表,则返回errInvalidUncleHash。
    86  	errInvalidUncleHash  = errors.New("non empty uncle hash")
    87  	errInvalidDifficulty = errors.New("invalid difficulty")
    88  
    89  //如果块的时间戳低于,则返回errInvalidTimestamp
    90  //上一个块的时间戳+最小块周期。
    91  	ErrInvalidTimestamp           = errors.New("invalid timestamp")
    92  	ErrWaitForPrevBlock           = errors.New("wait for last block arrived")
    93  	ErrMintFutureBlock            = errors.New("mint the future block")
    94  	ErrMismatchSignerAndValidator = errors.New("mismatch block signer and validator")
    95  	ErrInvalidBlockValidator      = errors.New("invalid block validator")
    96  	ErrInvalidMintBlockTime       = errors.New("invalid time to mint the block")
    97  	ErrNilBlockHeader             = errors.New("nil block header returned")
    98  )
    99  var (
   100  uncleHash = types.CalcUncleHash(nil) //作为叔叔,Keccak256(rlp([])在POW之外总是毫无意义的。
   101  )
   102  
   103  type Dpos struct {
   104  config *params.DposConfig //共识引擎配置参数
   105  db      ethdb.Database     //存储和检索快照检查点的数据库
   106  
   107  	signer               common.Address
   108  	signFn               SignerFn
   109  signatures           *lru.ARCCache //加快开采速度的近期区块特征
   110  	confirmedBlockHeader *types.Header
   111  
   112  	mu   sync.RWMutex
   113  	stop chan bool
   114  }
   115  
   116  type SignerFn func(accounts.Account, []byte) ([]byte, error)
   117  
   118  //注:Sighash是从集团复制的
   119  //sighash返回用作权限证明输入的哈希
   120  //签署。它是除65字节签名之外的整个头的哈希
   121  //包含在额外数据的末尾。
   122  //
   123  //注意,该方法要求额外数据至少为65字节,否则
   124  //恐慌。这样做是为了避免意外使用这两个表单(存在签名
   125  //或者不是),这可能会被滥用,从而为同一个头产生不同的散列。
   126  func sigHash(header *types.Header) (hash common.Hash) {
   127  	hasher := sha3.NewKeccak256()
   128  
   129  	rlp.Encode(hasher, []interface{}{
   130  		header.ParentHash,
   131  		header.UncleHash,
   132  		header.Validator,
   133  		header.Coinbase,
   134  		header.Root,
   135  		header.TxHash,
   136  		header.ReceiptHash,
   137  		header.Bloom,
   138  		header.Difficulty,
   139  		header.Number,
   140  		header.GasLimit,
   141  		header.GasUsed,
   142  		header.Time,
   143  header.Extra[:len(header.Extra)-65], //是的,如果多余的太短,这会很恐慌的
   144  		header.MixDigest,
   145  		header.Nonce,
   146  		header.DposContext.Root(),
   147  header.MaxValidatorSize,			//
   148  	})
   149  	hasher.Sum(hash[:0])
   150  
   151  	return hash
   152  }
   153  
   154  func New(config *params.DposConfig, db ethdb.Database) *Dpos {
   155  	signatures, _ := lru.NewARC(inmemorySignatures)
   156  
   157  	return &Dpos{
   158  		config:     config,
   159  		db:         db,
   160  		signatures: signatures,
   161  	}
   162  }
   163  
   164  func (d *Dpos) Author(header *types.Header) (common.Address, error) {
   165  	return header.Validator, nil
   166  }
   167  
   168  //验证批量是否符合共识算法规则
   169  func (d *Dpos) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool, blockInterval uint64) error {
   170  	return d.verifyHeader(chain, header, nil, blockInterval)
   171  }
   172  
   173  func (d *Dpos) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header,blockInterval uint64 ) error {
   174  	if header.Number == nil {
   175  		return errUnknownBlock
   176  	}
   177  	number := header.Number.Uint64()
   178  //不需要验证功能块
   179  	if header.Time.Cmp(big.NewInt(time.Now().Unix())) > 0 {
   180  		return consensus.ErrFutureBlock
   181  	}
   182  //检查额外数据是否包含虚荣和签名
   183  	if len(header.Extra) < extraVanity {
   184  		return errMissingVanity
   185  	}
   186  	if len(header.Extra) < extraVanity+extraSeal {
   187  		return errMissingSignature
   188  	}
   189  //确保混合摘要为零,因为我们当前没有分叉保护
   190  	if header.MixDigest != (common.Hash{}) {
   191  		return errInvalidMixDigest
   192  	}
   193  //困难总是1
   194  //度设定为1
   195  //
   196  	if header.Difficulty.Uint64() != 1 {		
   197  		return errInvalidDifficulty
   198  	}
   199  
   200  //确保块中不包含任何在DPO中无意义的叔叔。
   201  	if header.UncleHash != uncleHash {
   202  		return errInvalidUncleHash
   203  	}
   204  //如果所有检查都通过,则验证硬分叉的任何特殊字段
   205  	if err := misc.VerifyForkHashes(chain.Config(), header, false); err != nil {
   206  		return err
   207  	}
   208  
   209  	var parent *types.Header
   210  	if len(parents) > 0 {
   211  		parent = parents[len(parents)-1]
   212  	} else {
   213  		parent = chain.GetHeader(header.ParentHash, number-1)
   214  	}
   215  	if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash {
   216  		return consensus.ErrUnknownAncestor
   217  	}
   218  	if parent.Time.Uint64()+blockInterval> header.Time.Uint64() {
   219  		return ErrInvalidTimestamp
   220  	}
   221  	return nil
   222  }
   223  
   224  //批量验证区块头是否符合公共计算法规
   225  func (d *Dpos) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool,) (chan<- struct{}, <-chan error) {
   226  	abort := make(chan struct{})
   227  	results := make(chan error, len(headers))
   228  	blockInterval := chain.GetHeaderByNumber(0).BlockInterval
   229  
   230  	go func() {
   231  		for i, header := range headers {
   232  //header.extra=make([]字节,ExtraVanity+ExtraSeal)
   233  			err := d.verifyHeader(chain, header, headers[:i],blockInterval)
   234  			select {
   235  			case <-abort:
   236  				return
   237  			case results <- err:
   238  			}
   239  		}
   240  	}()
   241  	return abort, results
   242  }
   243  
   244  //verifyuncles实现converse.engine,始终返回任何
   245  //因为这个共识机制不允许叔叔。
   246  func (d *Dpos) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
   247  	if len(block.Uncles()) > 0 {
   248  		return errors.New("uncles not allowed")
   249  	}
   250  	return nil
   251  }
   252  
   253  //验证seal是否执行consension.engine,检查签名是否包含
   254  //头部满足共识协议要求。
   255  func (d *Dpos) VerifySeal(chain consensus.ChainReader, currentheader, genesisheader *types.Header) error {
   256  	return d.verifySeal(chain, currentheader, genesisheader,nil)
   257  }
   258  
   259  func (d *Dpos) verifySeal(chain consensus.ChainReader, currentheader, genesisheader *types.Header, parents []*types.Header) error {
   260  //验证不支持Genesis块
   261  	number := currentheader.Number.Uint64()
   262  	if number == 0 {
   263  		return errUnknownBlock
   264  	}
   265  	var parent *types.Header
   266  	if len(parents) > 0 {
   267  		parent = parents[len(parents)-1]
   268  	} else {
   269  		parent = chain.GetHeader(currentheader.ParentHash, number-1)
   270  	}
   271  
   272  	trieDB := trie.NewDatabase(d.db)
   273  dposContext, err := types.NewDposContextFromProto(trieDB, parent.DposContext) //零位
   274  
   275  	if err != nil {
   276  		return err
   277  	}
   278  	epochContext := &EpochContext{DposContext: dposContext}
   279  	blockInterVal := genesisheader.BlockInterval
   280  	validator, err := epochContext.lookupValidator(currentheader.Time.Int64(),blockInterVal)
   281  	if err != nil {
   282  		return err
   283  	}
   284  //
   285  	if err := d.verifyBlockSigner(validator, currentheader); err != nil {
   286  		return err
   287  	}
   288  	return d.updateConfirmedBlockHeader(chain)
   289  }
   290  
   291  func (d *Dpos) verifyBlockSigner(validator common.Address, header *types.Header) error {
   292  	signer, err := ecrecover(header, d.signatures)
   293  	if err != nil {
   294  		return err
   295  	}
   296  	if bytes.Compare(signer.Bytes(), validator.Bytes()) != 0 {
   297  		return ErrInvalidBlockValidator
   298  	}
   299  	if bytes.Compare(signer.Bytes(), header.Validator.Bytes()) != 0 {
   300  		return ErrMismatchSignerAndValidator
   301  	}
   302  	return nil
   303  }
   304  
   305  func (d *Dpos) updateConfirmedBlockHeader(chain consensus.ChainReader) error {
   306  	if d.confirmedBlockHeader == nil {
   307  		header, err := d.loadConfirmedBlockHeader(chain)
   308  		if err != nil {
   309  			header = chain.GetHeaderByNumber(0)
   310  			if header == nil {
   311  				return err
   312  			}
   313  		}
   314  		d.confirmedBlockHeader = header
   315  	}
   316  
   317  	curHeader := chain.CurrentHeader()
   318  
   319  	fmt.Println("+++++++++++++++++++555555++++++++++++++++++++++\n")
   320  	genesisHeader := chain.GetHeaderByNumber(0)
   321  	fmt.Println("+++++++++++++++++++from genesisBlock to get Maxvalidatorsize++++++++++++++++++++++\n")
   322  	epoch := int64(-1)
   323  	validatorMap := make(map[common.Address]bool)
   324  	for d.confirmedBlockHeader.Hash() != curHeader.Hash() &&
   325  		d.confirmedBlockHeader.Number.Uint64() < curHeader.Number.Uint64() {
   326  		curEpoch := curHeader.Time.Int64() / epochInterval
   327  		if curEpoch != epoch {
   328  			epoch = curEpoch
   329  			validatorMap = make(map[common.Address]bool)
   330  		}
   331  //快速返回
   332  //如果块数差小于一致同意的见证数
   333  //无需检查是否确认阻塞
   334  		consensusSize :=int(genesisHeader.MaxValidatorSize*2/3+1)
   335  		if curHeader.Number.Int64()-d.confirmedBlockHeader.Number.Int64() < int64(consensusSize-len(validatorMap)) {
   336  			log.Debug("Dpos fast return", "current", curHeader.Number.String(), "confirmed", d.confirmedBlockHeader.Number.String(), "witnessCount", len(validatorMap))
   337  			return nil
   338  		}
   339  		validatorMap[curHeader.Validator] = true
   340  		if len(validatorMap) >= consensusSize {
   341  			d.confirmedBlockHeader = curHeader
   342  			if err := d.storeConfirmedBlockHeader(d.db); err != nil {
   343  				return err
   344  			}
   345  			log.Debug("dpos set confirmed block header success", "currentHeader", curHeader.Number.String())
   346  			return nil
   347  		}
   348  		curHeader = chain.GetHeaderByHash(curHeader.ParentHash)
   349  		if curHeader == nil {
   350  			return ErrNilBlockHeader
   351  		}
   352  	}
   353  	return nil
   354  }
   355  
   356  func (s *Dpos) loadConfirmedBlockHeader(chain consensus.ChainReader) (*types.Header, error) {
   357  	key, err := s.db.Get(confirmedBlockHead)
   358  	if err != nil {
   359  		return nil, err
   360  	}
   361  	header := chain.GetHeaderByHash(common.BytesToHash(key))
   362  	if header == nil {
   363  		return nil, ErrNilBlockHeader
   364  	}
   365  	return header, nil
   366  }
   367  
   368  //存储将快照插入数据库。
   369  func (s *Dpos) storeConfirmedBlockHeader(db ethdb.Database) error {
   370  	return db.Put(confirmedBlockHead, s.confirmedBlockHeader.Hash().Bytes())
   371  }
   372  
   373  func (d *Dpos) Prepare(chain consensus.ChainReader, header *types.Header) error {
   374  	header.Nonce = types.BlockNonce{}
   375  	number := header.Number.Uint64()
   376  	if len(header.Extra) < extraVanity {
   377  		header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...)
   378  	}
   379  	header.Extra = header.Extra[:extraVanity]
   380  	header.Extra = append(header.Extra, make([]byte, extraSeal)...)
   381  	parent := chain.GetHeader(header.ParentHash, number-1)
   382  	if parent == nil {
   383  		return consensus.ErrUnknownAncestor
   384  	}
   385  	header.Difficulty = d.CalcDifficulty(chain, header.Time.Uint64(), parent)
   386  	header.Validator = d.signer
   387  	return nil
   388  }
   389  
   390  func AccumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) {
   391  //根据链进程选择正确的区块奖励
   392  	blockReward := frontierBlockReward
   393  	if config.IsByzantium(header.Number) {
   394  		blockReward = byzantiumBlockReward
   395  	}
   396  //为矿工和任何包括叔叔的人累积奖励
   397  	reward := new(big.Int).Set(blockReward)
   398  	state.AddBalance(header.Coinbase, reward)
   399  }
   400  
   401  //将出块周期内的交易打包进新的区域块中
   402  func (d *Dpos) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
   403  	uncles []*types.Header, receipts []*types.Receipt, dposContext *types.DposContext) (*types.Block, error) {
   404  //累积积木奖励并提交最终状态根
   405  	AccumulateRewards(chain.Config(), state, header, uncles)
   406  	header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
   407  
   408  	parent := chain.GetHeaderByHash(header.ParentHash)
   409  	epochContext := &EpochContext{
   410  		statedb:     state,
   411  		DposContext: dposContext,
   412  		TimeStamp:   header.Time.Int64(),
   413  	}
   414  	if timeOfFirstBlock == 0 {
   415  		if firstBlockHeader := chain.GetHeaderByNumber(1); firstBlockHeader != nil {
   416  			timeOfFirstBlock = firstBlockHeader.Time.Int64()
   417  		}
   418  	}
   419  	fmt.Println("++++++++++++++77777++++++++++++++++++\n")
   420  	fmt.Println("**************get genesis header********\n")
   421  	genesis := chain.GetHeaderByNumber(0)
   422  
   423  	err := epochContext.tryElect(genesis, parent)
   424  	if err != nil {
   425  		return nil, fmt.Errorf("got error when elect next epoch, err: %s", err)
   426  	}
   427  
   428  //更新薄荷计数trie
   429  	updateMintCnt(parent.Time.Int64(), header.Time.Int64(), header.Validator, dposContext)
   430  	header.DposContext = dposContext.ToProto()
   431  	return types.NewBlock(header, txs, uncles, receipts), nil
   432  }
   433  
   434  func (d *Dpos) checkDeadline(lastBlock *types.Block, now int64, blockInterval uint64) error {
   435  	prevSlot := PrevSlot(now, blockInterval)
   436  	nextSlot := NextSlot(now, blockInterval)
   437  	if lastBlock.Time().Int64() >= nextSlot {
   438  		return ErrMintFutureBlock
   439  	}
   440  //最后一个街区到了,或者时间到了
   441  	if lastBlock.Time().Int64() == prevSlot || nextSlot-now <= 1 {
   442  		return nil
   443  	}
   444  	return ErrWaitForPrevBlock
   445  }
   446  
   447  //检查当前的验证人员是否在当前的节点上
   448  func (d *Dpos) CheckValidator(lastBlock *types.Block, now int64,blockInterval uint64) error {
   449  	if err := d.checkDeadline(lastBlock, now, blockInterval); err != nil {
   450  		return err
   451  	}
   452  //
   453  	dposContext, err := types.NewDposContextFromProto(trie.NewDatabase(d.db), lastBlock.Header().DposContext)
   454  	if err != nil {
   455  		return err
   456  	}
   457  	epochContext := &EpochContext{DposContext: dposContext}
   458  	validator, err := epochContext.lookupValidator(now,blockInterval)
   459  	if err != nil {
   460  		return err
   461  	}
   462  	if (validator == common.Address{}) || bytes.Compare(validator.Bytes(), d.signer.Bytes()) != 0 {
   463  		return ErrInvalidBlockValidator
   464  	}
   465  	return nil
   466  }
   467  
   468  //Seal使用本地矿工的
   469  //密封顶部。
   470  //验证模块内容是否符合DPOSS计算法规(验证新模块是否应由该验证人员提出模块)
   471  func (d *Dpos) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error) {
   472  	header := block.Header()
   473  	number := header.Number.Uint64()
   474  //不支持密封Genesis块
   475  	if number == 0 {
   476  		return nil, errUnknownBlock
   477  	}
   478  	now := time.Now().Unix()
   479  	delay := NextSlot(now,chain.GetHeaderByNumber(0).BlockInterval) - now
   480  	if delay > 0 {
   481  		select {
   482  		case <-stop:
   483  			return nil, nil
   484  		case <-time.After(time.Duration(delay) * time.Second):
   485  		}
   486  	}
   487  	block.Header().Time.SetInt64(time.Now().Unix())
   488  
   489  //时间到了,在街区签名
   490  //对新块进行签名
   491  	sighash, err := d.signFn(accounts.Account{Address: d.signer}, sigHash(header).Bytes())
   492  	if err != nil {
   493  		return nil, err
   494  	}
   495  	copy(header.Extra[len(header.Extra)-extraSeal:], sighash)
   496  	return block.WithSeal(header), nil
   497  }
   498  
   499  func (d *Dpos) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
   500  	return big.NewInt(1)
   501  }
   502  
   503  func (d *Dpos) APIs(chain consensus.ChainReader) []rpc.API {
   504  	return []rpc.API{{
   505  		Namespace: "dpos",
   506  		Version:   "1.0",
   507  		Service:   &API{chain: chain, dpos: d},
   508  		Public:    true,
   509  	}}
   510  }
   511  
   512  func (d *Dpos) Authorize(signer common.Address, signFn SignerFn) {
   513  	d.mu.Lock()
   514  	d.signer = signer
   515  	d.signFn = signFn
   516  	d.mu.Unlock()
   517  }
   518  
   519  func (d *Dpos) Close() error {
   520  	return nil
   521  }
   522  
   523  //ecrecover从签名的头中提取以太坊帐户地址。
   524  func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) {
   525  //如果签名已经缓存,则返回
   526  	hash := header.Hash()
   527  	if address, known := sigcache.Get(hash); known {
   528  		return address.(common.Address), nil
   529  	}
   530  //从头中检索签名额外数据
   531  	if len(header.Extra) < extraSeal {
   532  		return common.Address{}, errMissingSignature
   533  	}
   534  	signature := header.Extra[len(header.Extra)-extraSeal:]
   535  //恢复公钥和以太坊地址
   536  	pubkey, err := crypto.Ecrecover(sigHash(header).Bytes(), signature)
   537  	if err != nil {
   538  		return common.Address{}, err
   539  	}
   540  	var signer common.Address
   541  	copy(signer[:], crypto.Keccak256(pubkey[1:])[12:])
   542  	sigcache.Add(hash, signer)
   543  	return signer, nil
   544  }
   545  
   546  func PrevSlot(now int64, blockInterval uint64) int64 {
   547  	return int64((now-1)/int64(blockInterval)) * int64(blockInterval)
   548  }
   549  
   550  func NextSlot(now int64, blockInterval uint64) int64 {
   551  	return int64((now+int64(blockInterval)-1)/int64(blockInterval)) * int64(blockInterval)
   552  }
   553  
   554  //更新Newblock矿工的mintcntrie计数
   555  //更新周期内验证人员出块数目的
   556  func updateMintCnt(parentBlockTime, currentBlockTime int64, validator common.Address, dposContext *types.DposContext) {
   557  	currentMintCntTrie := dposContext.MintCntTrie()
   558  	currentEpoch := parentBlockTime / epochInterval
   559  	currentEpochBytes := make([]byte, 8)
   560  	binary.BigEndian.PutUint64(currentEpochBytes, uint64(currentEpoch))
   561  
   562  	cnt := int64(1)
   563  	newEpoch := currentBlockTime / epochInterval
   564  //仍在当前报告期间
   565  	if currentEpoch == newEpoch {
   566  		iter := trie.NewIterator(currentMintCntTrie.NodeIterator(currentEpochBytes))
   567  
   568  //当电流不是起源时,从mintcntrie读取最后一个计数。
   569  		if iter.Next() {
   570  			cntBytes := currentMintCntTrie.Get(append(currentEpochBytes, validator.Bytes()...))
   571  
   572  //不是第一次造币
   573  			if cntBytes != nil {
   574  				cnt = int64(binary.BigEndian.Uint64(cntBytes)) + 1
   575  			}
   576  		}
   577  	}
   578  
   579  	newCntBytes := make([]byte, 8)
   580  	newEpochBytes := make([]byte, 8)
   581  	binary.BigEndian.PutUint64(newEpochBytes, uint64(newEpoch))
   582  	binary.BigEndian.PutUint64(newCntBytes, uint64(cnt))
   583  	dposContext.MintCntTrie().TryUpdate(append(newEpochBytes, validator.Bytes()...), newCntBytes)
   584  }
   585