github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/consensus/dpos/dpos.go (about)

     1  // Copyright 2019 The go-vnt Authors
     2  // This file is part of the go-vnt library.
     3  //
     4  // The go-vnt library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-vnt library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-vnt library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package dpos
    18  
    19  import (
    20  	"errors"
    21  	"math/big"
    22  	"sync"
    23  	"time"
    24  
    25  	"bytes"
    26  	"encoding/binary"
    27  	"fmt"
    28  
    29  	lru "github.com/hashicorp/golang-lru"
    30  	"github.com/vntchain/go-vnt/accounts"
    31  	"github.com/vntchain/go-vnt/common"
    32  	"github.com/vntchain/go-vnt/common/math"
    33  	"github.com/vntchain/go-vnt/consensus"
    34  	"github.com/vntchain/go-vnt/core"
    35  	"github.com/vntchain/go-vnt/core/state"
    36  	"github.com/vntchain/go-vnt/core/types"
    37  	"github.com/vntchain/go-vnt/core/vm/election"
    38  	"github.com/vntchain/go-vnt/crypto"
    39  	"github.com/vntchain/go-vnt/crypto/sha3"
    40  	"github.com/vntchain/go-vnt/log"
    41  	"github.com/vntchain/go-vnt/params"
    42  	"github.com/vntchain/go-vnt/rlp"
    43  	"github.com/vntchain/go-vnt/rpc"
    44  	"github.com/vntchain/go-vnt/vntdb"
    45  )
    46  
    47  const (
    48  	inMemorySignatures = 4096 // Number of recent block signatures to keep in memory
    49  	updateTimeLen      = 8    // Number of bytes the witnesses list update time take up
    50  )
    51  
    52  var (
    53  	VortexBlockReward     *big.Int = big.NewInt(24e+17) // 2.4VNT
    54  	VortexCandidatesBonus *big.Int = big.NewInt(16e+17) // 1.6VNT
    55  	// 2 seconds one block, 3 years producing about 47304000 blocks
    56  	stageTwoBlkNr = big.NewInt(47304000)
    57  	// 2 seconds one block, 6 years producing about 94608000 blocks
    58  	stageThreeBlkNr = big.NewInt(94608000)
    59  )
    60  
    61  // Various error messages to mark blocks invalid. These should be private to
    62  // prevent engine specific errors from being referenced in the remainder of the
    63  // codebase, inherently breaking if the engine is swapped out. Please put common
    64  // error types into the consensus package.
    65  var (
    66  	// errUnknownBlock is returned when the list of signers is requested for a block
    67  	// that is not part of the local blockchain.
    68  	errUnknownBlock = errors.New("unknown block")
    69  
    70  	// block has a beneficiary set to non-zeroes.
    71  	errInvalidCoinBase = errors.New("coinbase in block non-zero")
    72  
    73  	// errInvalidDifficulty is returned if the difficulty of a block is not 1
    74  	errInvalidDifficulty = errors.New("invalid difficulty")
    75  
    76  	// errInvalidTimestamp is returned if the timestamp of a block is lower than
    77  	// the previous block's timestamp + the minimum block period.
    78  	errInvalidTimestamp = errors.New("invalid timestamp")
    79  
    80  	// witness should be same with the parent
    81  	errWitnesses = errors.New("witnesses is different from parent")
    82  
    83  	// witness should in turn
    84  	errOutTurn = errors.New("witness is out turn")
    85  
    86  	// errNoPreviousWitness is returned if no previous witness still in current witness list
    87  	errNoPreviousWitness = errors.New("no previous witness still in current witness list")
    88  
    89  	// errInvalidExtraLen is returned if extra length is invalid
    90  	errInvalidExtraLen = errors.New("invalid Extra length")
    91  )
    92  
    93  type SignerFn func(accounts.Account, []byte) ([]byte, error)
    94  
    95  // getHeaderFromParentsFn get header from previous headers
    96  type getHeaderFromParentsFn func(hash common.Hash, num uint64) *types.Header
    97  
    98  type Dpos struct {
    99  	config         *params.DposConfig
   100  	bft            *BftManager
   101  	db             vntdb.Database // Database to store and retrieve dpos temp data, current not used
   102  	signatures     *lru.ARCCache  // Signatures of recent blocks to speed up block producing
   103  	signer         common.Address // VNT address of the signing key
   104  	signFn         SignerFn       // Signer function to authorize hashes with
   105  	lock           sync.RWMutex   // Protects the signer fields
   106  	updateInterval *big.Int       // Duration of update witnesses list
   107  	lastBounty     lastBountyInfo // 上次发放激励的信息
   108  
   109  	sendBftPeerUpdateFn func(urls []string)
   110  }
   111  
   112  type lastBountyInfo struct {
   113  	bountyHeight *big.Int // 上次发送激励的高度
   114  	updateHeight *big.Int // 更新当前数据的高度
   115  	sync.RWMutex          // 存在并发访问,加锁保护
   116  }
   117  
   118  // sigHash returns the hash which is used as input for the proof-of-authority
   119  // signing. It is the hash of the entire header apart from the 65 byte signature
   120  // contained at the end of the extra data.
   121  //
   122  // Note, the method requires the extra data to be at least 65 bytes, otherwise it
   123  // panics. This is done to avoid accidentally using both forms (signature present
   124  // or not), which could be abused to produce different hashes for the same header.
   125  func sigHash(header *types.Header) (hash common.Hash, err error) {
   126  	hasher := sha3.NewKeccak256()
   127  
   128  	err = rlp.Encode(hasher, []interface{}{
   129  		header.ParentHash,
   130  		header.Coinbase,
   131  		header.Root,
   132  		header.TxHash,
   133  		header.ReceiptHash,
   134  		header.Bloom,
   135  		header.Difficulty,
   136  		header.Number,
   137  		header.GasLimit,
   138  		header.GasUsed,
   139  		header.Time,
   140  		header.Extra,
   141  		header.Witnesses,
   142  	})
   143  	if err != nil {
   144  		return common.Hash{}, err
   145  	}
   146  
   147  	hasher.Sum(hash[:0])
   148  	return hash, nil
   149  }
   150  
   151  // ecrecover extracts the VNT account address from a signed header.
   152  func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) {
   153  	// If the signature's already cached, return that
   154  	hash := header.Hash()
   155  	if address, known := sigcache.Get(hash); known {
   156  		return address.(common.Address), nil
   157  	}
   158  
   159  	signature := header.Signature
   160  
   161  	// Recover the public key and the VNT address
   162  	sh, err := sigHash(header)
   163  	if err != nil {
   164  		return common.Address{}, err
   165  	}
   166  	pubkey, err := crypto.Ecrecover(sh.Bytes(), signature)
   167  	if err != nil {
   168  		return common.Address{}, fmt.Errorf("ecrecover fialed: %s", err.Error())
   169  	}
   170  	var signer common.Address
   171  	copy(signer[:], crypto.Keccak256(pubkey[1:])[12:])
   172  
   173  	sigcache.Add(hash, signer)
   174  	return signer, nil
   175  }
   176  
   177  // New creates a Delegated proof-of-stake consensus engine with the initial
   178  // signers set to the ones provided by the user.
   179  func New(config *params.DposConfig, db vntdb.Database) *Dpos {
   180  	signatures, _ := lru.NewARC(inMemorySignatures)
   181  
   182  	d := &Dpos{
   183  		config:         config,
   184  		bft:            nil,
   185  		db:             db,
   186  		signatures:     signatures,
   187  		updateInterval: nil,
   188  
   189  		lastBounty: lastBountyInfo{
   190  			bountyHeight: big.NewInt(0),
   191  			updateHeight: big.NewInt(0),
   192  		},
   193  	}
   194  
   195  	d.bft = newBftManager(d)
   196  	d.setUpdateInterval()
   197  
   198  	return d
   199  }
   200  
   201  func (d *Dpos) InitBft(sendBftMsg func(types.ConsensusMsg), SendPeerUpdate func(urls []string), verifyBlock func(*types.Block) (types.Receipts, []*types.Log, uint64, error), writeBlock func(*types.Block) error) {
   202  	d.sendBftPeerUpdateFn = SendPeerUpdate
   203  
   204  	// Init bft function
   205  	d.bft.sendBftMsg = sendBftMsg
   206  	d.bft.verifyBlock = verifyBlock
   207  	d.bft.writeBlock = writeBlock
   208  
   209  	// Init bft field
   210  	d.bft.coinBase = d.coinBase()
   211  
   212  	d.bft.producingStart()
   213  }
   214  
   215  // Author implements consensus.Engine, returning the VNT address recovered
   216  // from the signature in the header's extra-data section.
   217  func (d *Dpos) Author(header *types.Header) (common.Address, error) {
   218  	return ecrecover(header, d.signatures)
   219  }
   220  
   221  // VerifyHeader checks whether a header conforms to the consensus rules.
   222  func (d *Dpos) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {
   223  
   224  	err := d.verifyHeader(chain, header, nil)
   225  	if err != nil {
   226  		log.Debug("VerifyHeader error", "hash", header.Hash().String(), "err", err.Error())
   227  	} else {
   228  		log.Debug("VerifyHeader NO error", "hash", header.Hash().String(), "number", header.Number.Int64())
   229  	}
   230  	return err
   231  }
   232  
   233  // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The
   234  // method returns a quit channel to abort the operations and a results channel to
   235  // retrieve the async verifications (the order is that of the input slice).
   236  func (d *Dpos) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
   237  	abort := make(chan struct{})
   238  	results := make(chan error, len(headers))
   239  	go func() {
   240  		for i, header := range headers {
   241  			err := d.verifyHeader(chain, header, headers[:i])
   242  
   243  			select {
   244  			case <-abort:
   245  				return
   246  			case results <- err:
   247  			}
   248  		}
   249  	}()
   250  	return abort, results
   251  }
   252  
   253  // verifyHeader checks whether a header conforms to the consensus rules.The
   254  // caller may optionally pass in a batch of parents (ascending order) to avoid
   255  // looking those up from the database. This is useful for concurrently verifying
   256  // a batch of new headers.
   257  func (d *Dpos) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
   258  	if header.Number == nil {
   259  		return errUnknownBlock
   260  	}
   261  	number := header.Number.Uint64()
   262  
   263  	// todo verify header.time after implement bft without time trigger produce block
   264  	// Don't waste time checking blocks from the future
   265  	// if header.Time.Cmp(big.NewInt(time.Now().Unix())) > 0 {
   266  	// 	return consensus.ErrFutureBlock
   267  	// }
   268  
   269  	// Ensure extra has correct length' value checked in verify witnesses
   270  	if len(header.Extra) != updateTimeLen {
   271  		return errInvalidExtraLen
   272  	}
   273  
   274  	// Ensure that the block's difficulty is meaningful (may not be correct at this point)
   275  	if number > 0 {
   276  		if header.Difficulty == nil || header.Difficulty.Cmp(big.NewInt(1)) != 0 {
   277  			return errInvalidDifficulty
   278  		}
   279  	}
   280  	// All basic checks passed, verify cascading fields
   281  	return d.verifyCascadingFields(chain, header, parents)
   282  }
   283  
   284  // verifyCascadingFields verifies all the header fields that are not standalone,
   285  // rather depend on a batch of previous headers. The caller may optionally pass
   286  // in a batch of parents (ascending order) to avoid looking those up from the
   287  // database. This is useful for concurrently verifying a batch of new headers.
   288  func (d *Dpos) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
   289  	// The genesis block is the always valid dead-end
   290  	number := header.Number.Uint64()
   291  	if number == 0 {
   292  		return nil
   293  	}
   294  	// Ensure that the block's timestamp isn't too close to it's parent
   295  	var parent *types.Header
   296  	if len(parents) > 0 {
   297  		parent = parents[len(parents)-1]
   298  	} else {
   299  		parent = chain.GetHeader(header.ParentHash, number-1)
   300  	}
   301  	if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash {
   302  		return consensus.ErrUnknownAncestor
   303  	}
   304  
   305  	headerTime, parentTime := header.Time.Uint64(), parent.Time.Uint64()
   306  	if headerTime <= parentTime || (headerTime-parentTime)%d.config.Period != 0 {
   307  		log.Warn("Timestamp is invalid", "headerTime", headerTime, "parentTime", parentTime)
   308  		return errInvalidTimestamp
   309  	}
   310  
   311  	// Verify that the gas limit is <= 2^63-1
   312  	cap := uint64(0x7fffffffffffffff)
   313  	if header.GasLimit > cap {
   314  		return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap)
   315  	}
   316  	// Verify that the gasUsed is <= gasLimit
   317  	if header.GasUsed > header.GasLimit {
   318  		return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
   319  	}
   320  	// Verify that the gas limit remains within allowed bounds
   321  	diff := int64(parent.GasLimit) - int64(header.GasLimit)
   322  	if diff < 0 {
   323  		diff *= -1
   324  	}
   325  	limit := parent.GasLimit / params.GasLimitBoundDivisor
   326  	if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit {
   327  		return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit)
   328  	}
   329  
   330  	if len(header.Witnesses) != d.config.WitnessesNum {
   331  		return errWitnesses
   332  	}
   333  
   334  	// All basic checks passed, verify the seal and return
   335  	return d.verifySeal(chain, header, parents)
   336  }
   337  
   338  // VerifySeal implements consensus.Engine, checking whether the signature contained
   339  // in the header satisfies the consensus protocol requirements.
   340  func (d *Dpos) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
   341  	return d.verifySeal(chain, header, nil)
   342  }
   343  
   344  // verifySeal checks whether the signature contained in the header satisfies the
   345  // consensus protocol requirements. The method accepts an optional list of parent
   346  // headers that aren't yet part of the local blockchain to generate the snapshots
   347  // from.
   348  func (d *Dpos) verifySeal(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
   349  	// Verifying the genesis block is not supported
   350  	number := header.Number.Uint64()
   351  	if number == 0 {
   352  		return errUnknownBlock
   353  	}
   354  	// Resolve the authorization key and check against signers
   355  	signer, err := ecrecover(header, d.signatures)
   356  	if err != nil {
   357  		return err
   358  	}
   359  
   360  	if signer != header.Coinbase {
   361  		return errInvalidCoinBase
   362  	}
   363  
   364  	// 确认轮次对不对,是不是该这个节点出块
   365  	if !d.inTurn(header, signer, chain, parents) {
   366  		return errOutTurn
   367  	}
   368  	return nil
   369  }
   370  
   371  // VerifyWitnesses Verify witness list and update time(header.Extra) for DPoS
   372  func (d *Dpos) VerifyWitnesses(header *types.Header, db *state.StateDB, parent *types.Header) error {
   373  	updated, localWitnesses := d.getWitnesses(header, db, parent)
   374  	if len(localWitnesses) != len(header.Witnesses) {
   375  		return fmt.Errorf("witnesses length not match")
   376  	}
   377  
   378  	// Check header.Extra
   379  	if needSetUpdateTime(updated, header.Number.Uint64()) {
   380  		if !d.updatedWitnessCheckByTime(header) {
   381  			return fmt.Errorf("header.Extra is mismatch with header.Time when update")
   382  		}
   383  	} else {
   384  		if !bytes.Equal(header.Extra, parent.Extra) {
   385  			return fmt.Errorf("header.Extra is mismatch with parent.Time when NOT update")
   386  		}
   387  	}
   388  
   389  	// Check the witnesses list
   390  	for i := 0; i < len(localWitnesses); i++ {
   391  		if localWitnesses[i] != header.Witnesses[i] {
   392  			return fmt.Errorf("witnesses is not match")
   393  		}
   394  	}
   395  	return nil
   396  }
   397  
   398  // Prepare implements consensus.Engine, preparing all the consensus fields of the
   399  // header for running the transactions on top.
   400  func (d *Dpos) Prepare(chain consensus.ChainReader, header *types.Header) error {
   401  	var (
   402  		updated bool
   403  		err     error
   404  	)
   405  
   406  	number := header.Number.Uint64()
   407  	if number == 0 {
   408  		return errUnknownBlock
   409  	}
   410  
   411  	d.lock.RLock()
   412  	header.Coinbase = d.signer
   413  	d.lock.RUnlock()
   414  
   415  	// Set the correct difficulty
   416  	header.Difficulty = big.NewInt(1)
   417  
   418  	// Try to sleep if can not find parent header, try to stop commitNewWork start again immediately.
   419  	// WARN: there must be some db write or read error
   420  	parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1)
   421  	if parent == nil {
   422  		log.Error("Miss parent in dos.Prepare()", "hash", header.ParentHash.String(), "number", header.Number.Uint64()-1)
   423  		time.Sleep(time.Minute * 2)
   424  		return consensus.ErrUnknownAncestor
   425  	}
   426  
   427  	// Put next time in header
   428  	produceTime, nPeriod, err := d.nextProduceTime(parent.Time)
   429  	if err != nil {
   430  		return err
   431  	}
   432  	header.Time = produceTime
   433  
   434  	// Update witness list if needed,and set Extra with update value
   435  	updated, header.Witnesses, err = d.getWitnessesForProduce(header, chain, parent)
   436  	if err != nil {
   437  		return err
   438  	}
   439  
   440  	// Start a new round of bft
   441  	r := uint32(nPeriod.Uint64()) - 1
   442  	d.bft.blockRound = r
   443  	go d.bft.newRound(header.Number, r, header.Witnesses)
   444  
   445  	// Make sure self is the current block producer before produce
   446  	witness := header.Coinbase
   447  	if !d.inTurn(header, witness, chain, nil) {
   448  		log.Debug("Prepare failed", "err", errOutTurn)
   449  		return fmt.Errorf("node is out of turn")
   450  	}
   451  
   452  	// Fill Extra with the update time
   453  	// If this updated the witnesses list in this block, extra = this header time
   454  	// else, extra = last update time(get from parent's block)
   455  	header.Extra = make([]byte, updateTimeLen)
   456  	if needSetUpdateTime(updated, number) {
   457  		copy(header.Extra, encodeUpdateTime(header.Time))
   458  	} else {
   459  		copy(header.Extra, parent.Extra)
   460  	}
   461  
   462  	return nil
   463  }
   464  
   465  // needSetUpdateTime block 1 is special, should use it's header time instead of
   466  // genesis's extra, because genesis's extra is nil
   467  func needSetUpdateTime(update bool, number uint64) bool {
   468  	return update || number == 1
   469  }
   470  
   471  // Finalize implements consensus.Engine,  grants reward and returns the final block.
   472  func (d *Dpos) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, receipts []*types.Receipt) (*types.Block, error) {
   473  	// Granting bounty, if any left
   474  	if err := d.grantingReward(chain, header, state); err != nil {
   475  		return nil, err
   476  	}
   477  
   478  	// Commit db
   479  	header.Root = state.IntermediateRoot(true)
   480  
   481  	// Assemble and return the final block for sealing
   482  	return types.NewBlock(header, txs, receipts), nil
   483  }
   484  
   485  // grantingReward granting producing reward to the current block producer for producing this block,
   486  // and granting vote reward to all the active witness candidates. the vote reward, which each witness
   487  // earned, in direct proportion to it's vote percentage.
   488  // WARN: There is no reward if no VNT bounty left.
   489  func (d *Dpos) grantingReward(chain consensus.ChainReader, header *types.Header, state *state.StateDB) error {
   490  	if restBounty := election.QueryRestReward(state, header.Number); restBounty.Cmp(common.Big0) > 0 {
   491  		var err error
   492  		// Reward BP for producing this block
   493  		reward := curHeightBonus(header.Number, VortexBlockReward)
   494  		if restBounty.Cmp(reward) < 0 {
   495  			reward = restBounty
   496  		}
   497  		rewards := make(map[common.Address]*big.Int)
   498  		rewards[header.Coinbase] = reward
   499  		restBounty.Sub(restBounty, reward)
   500  
   501  		// 计算投票激励
   502  		// Reward all witness candidates, when update witness list, if has any bounty
   503  		if d.updatedWitnessCheckByTime(header) && restBounty.Cmp(common.Big0) > 0 {
   504  			candis, allBonus, err := d.voteBonusPreWork(chain, header, state)
   505  			if err != nil {
   506  				return err
   507  			}
   508  
   509  			// the amount of bounty granted must not greater than the left bounty
   510  			actualBonus := math.BigMin(allBonus, restBounty)
   511  			log.Debug("Vote bounty", "bounty(wei)", actualBonus.String())
   512  			d.calcVoteBounty(candis, actualBonus, rewards)
   513  		}
   514  
   515  		// 统一发放激励
   516  		if err = election.GrantReward(state, rewards, header.Number); err != nil {
   517  			log.Warn("Granting reward failed", "error", err.Error())
   518  			return err
   519  		}
   520  	}
   521  	return nil
   522  }
   523  
   524  // Authorize injects a private key into the consensus engine to mint new blocks
   525  // with.
   526  func (d *Dpos) Authorize(signer common.Address, signFn SignerFn) {
   527  	d.lock.Lock()
   528  	defer d.lock.Unlock()
   529  
   530  	d.signer = signer
   531  	d.signFn = signFn
   532  }
   533  
   534  // Seal implements consensus.Engine, attempting to create a sealed block using
   535  // the local signing credentials.
   536  func (d *Dpos) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error) {
   537  	header := block.Header()
   538  
   539  	// Sealing the genesis block is not supported
   540  	number := header.Number.Uint64()
   541  	if number == 0 {
   542  		return nil, errUnknownBlock
   543  	}
   544  
   545  	// Don't hold the witness fields for the entire sealing procedure
   546  	d.lock.RLock()
   547  	witness, signFn := d.signer, d.signFn
   548  	d.lock.RUnlock()
   549  
   550  	// Sign all the things without Signature
   551  	sh, err := sigHash(header)
   552  	if err != nil {
   553  		return nil, err
   554  	}
   555  	sighash, err := signFn(accounts.Account{Address: witness}, sh.Bytes())
   556  	if err != nil {
   557  		return nil, err
   558  	}
   559  	header.Signature = make([]byte, len(sighash))
   560  	copy(header.Signature[:], sighash)
   561  
   562  	log.Info("Seal block", "at time", time.Now().Unix())
   563  	d.bft.startPrePrepare(block.WithSeal(header))
   564  	// DPoS no need return block
   565  	return nil, nil
   566  }
   567  
   568  // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
   569  // that a new block should have based on the previous blocks in the chain and the
   570  // current signer.
   571  func (d *Dpos) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
   572  	return common.Big1
   573  }
   574  
   575  // APIs implements consensus.Engine, returning the user facing RPC API to allow
   576  // controlling the signer voting.
   577  func (d *Dpos) APIs(chain consensus.ChainReader) []rpc.API {
   578  	return []rpc.API{{
   579  		Namespace: "dpos",
   580  		Version:   "1.0",
   581  		Service:   &API{chain: chain, dpos: d},
   582  		Public:    false,
   583  	}}
   584  }
   585  
   586  // nextProduceTime calculate next block produce time with previous block time
   587  // 		cur_time = time()
   588  // 		dur = cur_time - parent_time
   589  // 		nPeriod = dur / interval
   590  // 		// always up bound
   591  // 		nPeriod++
   592  // 		return parent_time + diff_index * interval
   593  func (d *Dpos) nextProduceTime(preBlockTime *big.Int) (produceTime *big.Int, nPeriod *big.Int, err error) {
   594  	now := time.Now().Unix()
   595  	dur := new(big.Int).Sub(new(big.Int).SetInt64(now), preBlockTime)
   596  	period := new(big.Int).SetUint64(d.config.Period)
   597  	// the unit is second, even no left of DivMod, but current time is in new period
   598  	nPeriod = new(big.Int).Div(dur, period)
   599  	nPeriod.Add(nPeriod, common.Big1)
   600  
   601  	nextTime := new(big.Int).Mul(nPeriod, period)
   602  	nextTime.Add(nextTime, preBlockTime)
   603  
   604  	return nextTime, nPeriod, nil
   605  }
   606  
   607  func (d *Dpos) inTurn(header *types.Header, witness common.Address, chain consensus.ChainReader, parents []*types.Header) bool {
   608  	var (
   609  		preWitness common.Address
   610  		preTime    *big.Int
   611  		manager    *Manager
   612  		err        error
   613  	)
   614  
   615  	getHeaderFromParents := func(hash common.Hash, num uint64) *types.Header {
   616  		if len(parents) == 0 {
   617  			return nil
   618  		}
   619  
   620  		for i := len(parents) - 1; i >= 0; i-- {
   621  			if parents[i].Hash() == hash && parents[i].Number.Uint64() == num {
   622  				return parents[i]
   623  			}
   624  		}
   625  		return nil
   626  	}
   627  
   628  	number := header.Number.Uint64()
   629  	// using current block's witness list create manager
   630  	if manager, err = d.manager(header); err != nil {
   631  		log.Warn("Not find manager", "err", err.Error(), "number", number)
   632  		return false
   633  	}
   634  
   635  	// first block always belongs to first witness
   636  	if number == 1 {
   637  		if len(manager.Witnesses) > 0 && manager.Witnesses[0] == witness {
   638  			return true
   639  		} else {
   640  			return false
   641  		}
   642  	}
   643  
   644  	preWitness, preTime, err = d.previousWitness(manager, chain, header.ParentHash, number-1, getHeaderFromParents)
   645  	if err == errNoPreviousWitness {
   646  		return manager.Witnesses[0] == witness
   647  	} else if err != nil {
   648  		log.Warn("Not find preWitness", "err", err.Error())
   649  		return false
   650  	}
   651  
   652  	return manager.inTurn(witness, preWitness, header.Time, preTime)
   653  }
   654  
   655  // previousWitness find the previous witness who still in current witness list
   656  func (d *Dpos) previousWitness(manager *Manager, chain consensus.ChainReader, hash common.Hash, number uint64, getHeaderFromParents getHeaderFromParentsFn) (witness common.Address, produceTime *big.Int, err error) {
   657  	var header *types.Header
   658  
   659  	find := false
   660  	for !find {
   661  		if number == 0 {
   662  			return witness, produceTime, errNoPreviousWitness
   663  		}
   664  
   665  		header = getHeaderFromParents(hash, number)
   666  		if header == nil {
   667  			header = chain.GetHeader(hash, number)
   668  		}
   669  		if header == nil {
   670  			return witness, produceTime, fmt.Errorf("can not find block header hash: %x, at hight: %d", hash, number)
   671  		}
   672  
   673  		// check is witness still valid
   674  		witness = header.Coinbase
   675  		find = manager.has(witness)
   676  		if find {
   677  			break
   678  		}
   679  
   680  		hash, number = header.ParentHash, number-1
   681  	}
   682  
   683  	// produce time from parent
   684  	produceTime = header.Time
   685  
   686  	return witness, produceTime, nil
   687  }
   688  
   689  // manager create a witness list manager using header
   690  func (d *Dpos) manager(header *types.Header) (*Manager, error) {
   691  	if len(header.Witnesses) == 0 {
   692  		return nil, fmt.Errorf("header.Witnesses is empty")
   693  	}
   694  
   695  	// using header's witness list create manager
   696  	return NewManager(d.config.Period, header.Witnesses), nil
   697  }
   698  
   699  // getWitnessesForProduce Get the first N candidates as witnesses from chain
   700  func (d *Dpos) getWitnessesForProduce(header *types.Header, chain consensus.ChainReader, parent *types.Header) (bool, []common.Address, error) {
   701  	var (
   702  		bc *core.BlockChain
   703  		ok bool
   704  	)
   705  
   706  	// get state db from parent's root
   707  	if bc, ok = chain.(*core.BlockChain); !ok {
   708  		return false, nil, fmt.Errorf("getWitnessesForProduce, get block chain instance error")
   709  	}
   710  	db, err := bc.StateAt(parent.Root)
   711  	if db == nil {
   712  		return false, nil, err
   713  	}
   714  
   715  	updated, witnesses := d.getWitnesses(header, db, parent)
   716  	return updated, witnesses, nil
   717  }
   718  
   719  // getWitnesses 根据当前情况,判断从指定的state db读取或者使用前一个区块的
   720  func (d *Dpos) getWitnesses(header *types.Header, db *state.StateDB, parent *types.Header) (bool, []common.Address) {
   721  	var (
   722  		witnesses      []common.Address
   723  		lastUpdateTime *big.Int
   724  		urls           []string
   725  	)
   726  
   727  	// Get last update witnesses list time from parent block
   728  	if parent.Number.Int64() == 0 {
   729  		lastUpdateTime = parent.Time
   730  	} else {
   731  		var upTime updateTime
   732  		copy(upTime[:], parent.Extra[:updateTimeLen])
   733  		lastUpdateTime = upTime.bigInt()
   734  	}
   735  
   736  	need := d.needUpdateWitnesses(header.Time, lastUpdateTime)
   737  	if need {
   738  		log.Debug("Get new witness from db", "height", header.Number.String())
   739  		witnesses, urls = d.GetWitnessesFromStateDB(db)
   740  	}
   741  
   742  	// Using parent's witnesses, when update failed or No need update
   743  	updated := need
   744  	if len(witnesses) == 0 {
   745  		witnesses = parent.Witnesses
   746  		updated = false
   747  	}
   748  	if updated && d.sendBftPeerUpdateFn != nil {
   749  		d.sendBftPeerUpdateFn(urls)
   750  	}
   751  	return updated, witnesses
   752  }
   753  
   754  // GetWitnessesFromStateDB Get the first N candidates as witnesses from stateDB
   755  // It's can be used for get produce block and verify witnesses
   756  func (d *Dpos) GetWitnessesFromStateDB(stateDB *state.StateDB) ([]common.Address, []string) {
   757  	if stateDB == nil {
   758  		log.Error("GetWitnessesFromStateDB, stateDB is nil")
   759  	}
   760  
   761  	return election.GetFirstNCandidates(stateDB, d.config.WitnessesNum)
   762  }
   763  
   764  // needUpdateWitnesses weather current time needs update witnesses list
   765  func (d *Dpos) needUpdateWitnesses(t *big.Int, lastUpdateTime *big.Int) bool {
   766  	log.Debug("needUpdateWitnesses", "last", lastUpdateTime.String(), "current", t.String())
   767  	dur := new(big.Int).Sub(t, lastUpdateTime)
   768  	return dur.Cmp(d.updateInterval) >= 0
   769  }
   770  
   771  // setUpdateInterval only called when start up
   772  func (d *Dpos) setUpdateInterval() {
   773  	d.updateInterval = new(big.Int).SetUint64(3 * uint64(d.config.WitnessesNum) * d.config.Period)
   774  }
   775  
   776  // coinBase get the address of this producer
   777  func (d *Dpos) coinBase() (cb common.Address) {
   778  	d.lock.RLock()
   779  	cb = d.signer
   780  	d.lock.RUnlock()
   781  	return
   782  }
   783  
   784  // HandleBftMsg handle the bft message received from peer.
   785  func (d *Dpos) HandleBftMsg(chain consensus.ChainReader, msg types.ConsensusMsg) {
   786  	go d.bft.handleBftMsg(msg)
   787  }
   788  
   789  func (d *Dpos) CleanOldMsg(h *big.Int) {
   790  	d.bft.cleanOldMsg(h)
   791  }
   792  
   793  func (d *Dpos) VerifyCommitMsg(block *types.Block) error {
   794  	return d.bft.VerifyCmtMsgOf(block)
   795  }
   796  
   797  func (d *Dpos) ProducingStop() {
   798  	d.bft.producingStop()
   799  }
   800  
   801  type updateTime [updateTimeLen]byte
   802  
   803  func encodeUpdateTime(uTime *big.Int) []byte {
   804  	var upTime updateTime
   805  	binary.BigEndian.PutUint64(upTime[:], uTime.Uint64())
   806  	return upTime[:]
   807  }
   808  
   809  func (upTime *updateTime) bigInt() *big.Int {
   810  	uTime := binary.BigEndian.Uint64(upTime[:])
   811  	return big.NewInt(0).SetUint64(uTime)
   812  }
   813  
   814  // calcVoteBounty returns a map, which contains the vote bonus of each candidates
   815  // in this period. If active candidates less than WitnessesNum it will not reward candidate.
   816  func (d *Dpos) calcVoteBounty(candis election.CandidateList, allBonus *big.Int, rewards map[common.Address]*big.Int) {
   817  	totalVotes := big.NewInt(0)
   818  	activeCnt := 0
   819  	for _, can := range candis {
   820  		if !can.Active() {
   821  			continue
   822  		}
   823  		totalVotes.Add(totalVotes, can.VoteCount)
   824  		activeCnt++
   825  	}
   826  	// Too less candidates before main net start, but it's normal
   827  	if activeCnt < d.config.WitnessesNum || totalVotes.Cmp(common.Big0) == 0 {
   828  		return
   829  	}
   830  
   831  	// Calc each candidates' bonus
   832  	for _, can := range candis {
   833  		if !can.Active() {
   834  			continue
   835  		}
   836  
   837  		reward := big.NewInt(0).Mul(allBonus, can.VoteCount)
   838  		reward.Div(reward, totalVotes)
   839  		if _, ok := rewards[can.Owner]; ok {
   840  			rewards[can.Owner] = big.NewInt(0).Add(rewards[can.Owner], reward)
   841  		} else {
   842  			rewards[can.Owner] = reward
   843  		}
   844  	}
   845  }
   846  
   847  // voteBonusPreWork
   848  // 1) calculate vote bonus
   849  // 2) get witness candidates of last update witness
   850  func (d *Dpos) voteBonusPreWork(chain consensus.ChainReader, header *types.Header,
   851  	curStateDB *state.StateDB) (election.CandidateList, *big.Int, error) {
   852  	var (
   853  		bc *core.BlockChain
   854  		ok bool
   855  	)
   856  	// Block 1, no need bonus, it's no error
   857  	if header.Number.Cmp(common.Big1) <= 0 {
   858  		return make(election.CandidateList, 0), big.NewInt(0), nil
   859  	}
   860  
   861  	// Get state db from previous block
   862  	if bc, ok = chain.(*core.BlockChain); !ok {
   863  		return nil, nil, fmt.Errorf("voteBonusPreWork, get block chain instance error")
   864  	}
   865  
   866  	// Calc all vote bonus
   867  	// the last block number of calculate vote reward is the last block number of updating witness list
   868  	lastCalcBountyBlkNr := d.lastBountyBlkNr(header, bc)
   869  	log.Debug("Bounus", "lastCalcBountyBlkNr", lastCalcBountyBlkNr.String())
   870  	allBonus := big.NewInt(0).Sub(header.Number, lastCalcBountyBlkNr)
   871  	if allBonus.Sign() <= 0 {
   872  		return make(election.CandidateList, 0), big.NewInt(0), nil
   873  	}
   874  	allBonus.Mul(allBonus, curHeightBonus(header.Number, VortexCandidatesBonus))
   875  
   876  	// Get all witnesses candidates
   877  	lastCandis := election.GetAllCandidates(curStateDB, false)
   878  
   879  	return lastCandis, allBonus, nil
   880  }
   881  
   882  // lastBountyBlkNr returns the block number of last update witness list. Returns
   883  // the current block number if not find. This prevents excessive incentives.
   884  // 见证人列表长时间未更新时,可能查找耗时,所以设置缓存数据,
   885  // 同过度的下次查找将不再耗时。
   886  // 不同高度的话,必然已经进行了下一轮见证人列表更新,以链上数据
   887  // 为准,所以进行查找,然后记录数据。
   888  func (d *Dpos) lastBountyBlkNr(header *types.Header, bc *core.BlockChain) (bh *big.Int) {
   889  	// 数据老旧时,尝试更新数据
   890  	d.lastBounty.RLock()
   891  	outdated := d.lastBounty.updateHeight.Cmp(header.Number) < 0
   892  	d.lastBounty.RUnlock()
   893  	if outdated {
   894  		h := bc.CurrentHeader()
   895  		for !d.updatedWitnessCheckByTime(h) && h != nil {
   896  			h = bc.GetHeaderByHash(h.ParentHash)
   897  		}
   898  		if h != nil {
   899  			bh = new(big.Int).Set(h.Number)
   900  		} else {
   901  			bh = new(big.Int).Set(header.Number)
   902  		}
   903  
   904  		d.lastBounty.Lock()
   905  		d.lastBounty.bountyHeight.Set(bh)
   906  		d.lastBounty.updateHeight.Set(header.Number)
   907  		d.lastBounty.Unlock()
   908  		return
   909  	}
   910  
   911  	// 本高度已查找过,使用已查得数据
   912  	d.lastBounty.RLock()
   913  	bh = big.NewInt(0).Set(d.lastBounty.bountyHeight)
   914  	d.lastBounty.RUnlock()
   915  
   916  	return bh
   917  }
   918  
   919  // updatedWitnessCheckByTime using time to check whether this block updated
   920  // witness list or not.
   921  func (d *Dpos) updatedWitnessCheckByTime(header *types.Header) bool {
   922  	if len(header.Extra) < updateTimeLen {
   923  		return false
   924  	}
   925  
   926  	var upTime updateTime
   927  	copy(upTime[:], header.Extra[:updateTimeLen])
   928  	uTime := upTime.bigInt()
   929  	return uTime.Cmp(header.Time) == 0
   930  }
   931  
   932  // curHeightBonus return the VNT bonus at blkNr block number.
   933  func curHeightBonus(blkNr *big.Int, initBonus *big.Int) *big.Int {
   934  	var denominator *big.Int
   935  	if blkNr.Cmp(stageTwoBlkNr) < 0 {
   936  		return initBonus
   937  	} else if blkNr.Cmp(stageThreeBlkNr) < 0 {
   938  		denominator = common.Big2
   939  	} else {
   940  		denominator = common.Big4
   941  	}
   942  
   943  	return big.NewInt(0).Div(initBonus, denominator)
   944  }