github.com/cheng762/platon-go@v1.8.17-0.20190529111256-7deff2d7be26/consensus/cbft/ppos.go (about)

     1  package cbft
     2  
     3  import (
     4  	"github.com/PlatONnetwork/PlatON-Go/common"
     5  	"github.com/PlatONnetwork/PlatON-Go/core"
     6  	"github.com/PlatONnetwork/PlatON-Go/core/ppos"
     7  	"github.com/PlatONnetwork/PlatON-Go/core/state"
     8  	"github.com/PlatONnetwork/PlatON-Go/core/types"
     9  	"github.com/PlatONnetwork/PlatON-Go/core/vm"
    10  	"github.com/PlatONnetwork/PlatON-Go/log"
    11  	"github.com/PlatONnetwork/PlatON-Go/p2p/discover"
    12  	"github.com/PlatONnetwork/PlatON-Go/params"
    13  	"fmt"
    14  	"math/big"
    15  	"sync"
    16  	"github.com/PlatONnetwork/PlatON-Go/core/ppos_storage"
    17  )
    18  
    19  type ppos struct {
    20  
    21  	nodeRound 		  roundCache
    22  	//chain             *core.BlockChain
    23  	lastCycleBlockNum uint64
    24  	// A round of consensus start time is usually the block time of the last block at the end of the last round of consensus;
    25  	// if it is the first round, it starts from 1970.1.1.0.0.0.0. Unit: second
    26  	startTimeOfEpoch  int64
    27  	config            *params.PposConfig
    28  
    29  	// added by candidateContext module
    30  	lock 					sync.RWMutex
    31  	// the candidateContext pool object pointer
    32  	candidateContext 	*pposm.CandidatePoolContext
    33  	// the ticket pool object pointer
    34  	ticketContext				*pposm.TicketPoolContext
    35  
    36  	pposTemp 			*ppos_storage.PPOS_TEMP
    37  }
    38  
    39  
    40  
    41  func newPpos(config *params.CbftConfig) *ppos {
    42  	return &ppos{
    43  		lastCycleBlockNum: 	0,
    44  		config:            	config.PposConfig,
    45  		candidateContext:   pposm.NewCandidatePoolContext(config.PposConfig),
    46  		ticketContext: 		pposm.NewTicketPoolContext(config.PposConfig),
    47  	}
    48  }
    49  
    50  
    51  func (p *ppos) BlockProducerIndex(parentNumber *big.Int, parentHash common.Hash, blockNumber *big.Int, nodeID discover.NodeID, round int32) (int64, []discover.NodeID) {
    52  	p.lock.RLock()
    53  	defer p.lock.RUnlock()
    54  
    55  	log.Info("BlockProducerIndex", "parentNumber", parentNumber, "parentHash", parentHash.String(), "blockNumber", blockNumber.String(), "nodeID", nodeID.String(), "round", round)
    56  
    57  	nodeCache := p.nodeRound.getNodeCache(parentNumber, parentHash)
    58  	p.printMapInfo("BlockProducerIndex", parentNumber.Uint64(), parentHash)
    59  	if nodeCache != nil {
    60  		_former := nodeCache.former
    61  		_current := nodeCache.current
    62  		_next := nodeCache.next
    63  
    64  		switch round {
    65  		case former:
    66  			if _former != nil && _former.start != nil && _former.end != nil && blockNumber.Cmp(_former.start) >= 0 && blockNumber.Cmp(_former.end) <= 0 {
    67  				return p.roundIndex(nodeID, _former), _former.nodeIds
    68  			}
    69  
    70  		case current:
    71  			if _current != nil && _current.start != nil && _current.end != nil && blockNumber.Cmp(_current.start) >= 0 && blockNumber.Cmp(_current.end) <= 0 {
    72  				return p.roundIndex(nodeID, _current), _current.nodeIds
    73  			}
    74  
    75  		case next:
    76  			if _next != nil && _next.start != nil && _next.end != nil && blockNumber.Cmp(_next.start) >= 0 && blockNumber.Cmp(_next.end) <= 0 {
    77  				return p.roundIndex(nodeID, _next), _next.nodeIds
    78  			}
    79  
    80  		default:
    81  			if _former != nil && _former.start != nil && _former.end != nil && blockNumber.Cmp(_former.start) >= 0 && blockNumber.Cmp(_former.end) <= 0 {
    82  				return p.roundIndex(nodeID, _former), _former.nodeIds
    83  			} else if _current != nil && _current.start != nil && _current.end != nil && blockNumber.Cmp(_current.start) >= 0 && blockNumber.Cmp(_current.end) <= 0 {
    84  				return p.roundIndex(nodeID, _current), _current.nodeIds
    85  			} else if _next != nil && _next.start != nil && _next.end != nil && blockNumber.Cmp(_next.start) >= 0 && blockNumber.Cmp(_next.end) <= 0 {
    86  				return p.roundIndex(nodeID, _next), _next.nodeIds
    87  			}
    88  		}
    89  	}
    90  	return -1, nil
    91  }
    92  
    93  func (p *ppos) roundIndex(nodeID discover.NodeID, round *pposRound) int64 {
    94  	for idx, nid := range round.nodeIds {
    95  		if nid == nodeID {
    96  			return int64(idx)
    97  		}
    98  	}
    99  	return -1
   100  }
   101  
   102  func (p *ppos) NodeIndexInFuture(nodeID discover.NodeID) int64 {
   103  	return -1
   104  }
   105  
   106  func (p *ppos) getFormerNodes (parentNumber *big.Int, parentHash common.Hash, blockNumber *big.Int) []*discover.Node {
   107  	p.lock.RLock()
   108  	defer p.lock.RUnlock()
   109  
   110  	formerRound := p.nodeRound.getFormerRound(parentNumber, parentHash)
   111  	if formerRound != nil && len(formerRound.nodes) > 0 && blockNumber.Cmp(formerRound.start) >= 0 && blockNumber.Cmp(formerRound.end) <= 0{
   112  		return formerRound.nodes
   113  	}
   114  	return nil
   115  }
   116  
   117  func (p *ppos) getCurrentNodes (parentNumber *big.Int, parentHash common.Hash, blockNumber *big.Int) []*discover.Node {
   118  	p.lock.RLock()
   119  	defer p.lock.RUnlock()
   120  
   121  	currentRound := p.nodeRound.getCurrentRound(parentNumber, parentHash)
   122  	if currentRound != nil && currentRound.start != nil && currentRound.end != nil && len(currentRound.nodes) > 0 && blockNumber.Cmp(currentRound.start) >= 0 && blockNumber.Cmp(currentRound.end) <= 0{
   123  		return currentRound.nodes
   124  	}
   125  	return nil
   126  }
   127  
   128  
   129  func (p *ppos) consensusNodes(parentNumber *big.Int, parentHash common.Hash, blockNumber *big.Int) []discover.NodeID {
   130  	p.lock.RLock()
   131  	defer p.lock.RUnlock()
   132  
   133  	log.Debug("call consensusNodes", "parentNumber", parentNumber.Uint64(), "parentHash", parentHash, "blockNumber", blockNumber.Uint64())
   134  	nodeCache := p.nodeRound.getNodeCache(parentNumber, parentHash)
   135  	p.printMapInfo("consensusNodes nodeCache", parentNumber.Uint64(), parentHash)
   136  	if nodeCache != nil {
   137  		if nodeCache.former != nil && nodeCache.former.start != nil && nodeCache.former.end != nil && blockNumber.Cmp(nodeCache.former.start) >= 0 && blockNumber.Cmp(nodeCache.former.end) <= 0 {
   138  			return nodeCache.former.nodeIds
   139  		} else if nodeCache.current != nil && nodeCache.current.start != nil && nodeCache.current.end != nil && blockNumber.Cmp(nodeCache.current.start) >= 0 && blockNumber.Cmp(nodeCache.current.end) <= 0 {
   140  			return nodeCache.current.nodeIds
   141  		} else if nodeCache.next != nil && nodeCache.next.start != nil && nodeCache.next.end != nil && blockNumber.Cmp(nodeCache.next.start) >= 0 && blockNumber.Cmp(nodeCache.next.end) <= 0 {
   142  			return nodeCache.next.nodeIds
   143  		}
   144  	}
   145  	return nil
   146  }
   147  
   148  func (p *ppos) LastCycleBlockNum() uint64 {
   149  	// Get the block height at the end of the final round of consensus
   150  	return p.lastCycleBlockNum
   151  }
   152  
   153  func (p *ppos) SetLastCycleBlockNum(blockNumber uint64) {
   154  	// Set the block height at the end of the last round of consensus
   155  	p.lastCycleBlockNum = blockNumber
   156  }
   157  
   158  
   159  func (p *ppos) StartTimeOfEpoch() int64 {
   160  	return p.startTimeOfEpoch
   161  }
   162  
   163  func (p *ppos) SetStartTimeOfEpoch(startTimeOfEpoch int64) {
   164  	p.startTimeOfEpoch = startTimeOfEpoch
   165  }
   166  
   167  /** ppos was added func */
   168  /** Method provided to the cbft module call */
   169  // Announce witness
   170  func (p *ppos) Election(state *state.StateDB, parentHash common.Hash, currBlocknumber *big.Int) ([]*discover.Node, error) {
   171  	if nextNodes, err := p.candidateContext.Election(state, parentHash, currBlocknumber); nil != err {
   172  		log.Error("PPOS Election next witness", " err: ", err)
   173  		/*panic("Election error " + err.Error())*/
   174  		return nil, err
   175  	} else {
   176  		//d.candidateContext.ForEachStorage(state, "PPOS Election finish,view stateDB content again ...")
   177  		return nextNodes, nil
   178  	}
   179  }
   180  
   181  // switch next witnesses to current witnesses
   182  func (p *ppos) Switch(state *state.StateDB, blockNumber *big.Int) bool {
   183  	log.Info("Switch begin...")
   184  	if !p.candidateContext.Switch(state, blockNumber) {
   185  		return false
   186  	}
   187  	log.Info("Switch success...")
   188  	p.candidateContext.GetAllWitness(state, blockNumber)
   189  
   190  	return true
   191  }
   192  
   193  // Getting nodes of witnesses
   194  // flag:-1: the previous round of witnesses  0: the current round of witnesses   1: the next round of witnesses
   195  func (p *ppos) GetWitness(state *state.StateDB, flag int, blockNumber *big.Int) ([]*discover.Node, error) {
   196  	return p.candidateContext.GetWitness(state, flag, blockNumber)
   197  }
   198  
   199  func (p *ppos) GetAllWitness(state *state.StateDB, blockNumber *big.Int) ([]*discover.Node, []*discover.Node, []*discover.Node, error) {
   200  	return p.candidateContext.GetAllWitness(state, blockNumber)
   201  }
   202  
   203  // Getting can by witnesses
   204  // flag:
   205  // -1: 		previous round
   206  // 0:		current round
   207  // 1: 		next round
   208  func (p *ppos) GetWitnessCandidate (state vm.StateDB, nodeId discover.NodeID, flag int, blockNumber *big.Int) *types.Candidate {
   209  	return p.candidateContext.GetWitnessCandidate(state, nodeId, flag, blockNumber)
   210  }
   211  
   212  // setting candidate pool of ppos module
   213  func (p *ppos) SetCandidateContextOption(blockChain *core.BlockChain, initialNodes []discover.Node) {
   214  	log.Info("Start node, build the nodeRound ...")
   215  
   216  	genesis := blockChain.Genesis()
   217  
   218  	// init roundCache by config
   219  	p.buildGenesisRound(genesis.NumberU64(), genesis.Hash(), initialNodes)
   220  	p.printMapInfo("Read Genesis block configuration at startup:", genesis.NumberU64(), genesis.Hash())
   221  
   222  	// When the highest block in the chain is not a genesis block, Need to load witness nodeIdList from the stateDB.
   223  	if genesis.NumberU64() != blockChain.CurrentBlock().NumberU64() {
   224  
   225  		currentBlock := blockChain.CurrentBlock()
   226  		var currBlockNumber uint64
   227  		var currBlockHash common.Hash
   228  		var currentBigInt *big.Int
   229  
   230  		currBlockNumber = blockChain.CurrentBlock().NumberU64()
   231  		currentBigInt = blockChain.CurrentBlock().Number()
   232  		currBlockHash = blockChain.CurrentBlock().Hash()
   233  
   234  
   235  
   236  		count := 0
   237  		blockArr := make([]*types.Block, 0)
   238  		for {
   239  			if currBlockNumber == genesis.NumberU64() || count == common.BaseIrrCount {
   240  				break
   241  			}
   242  
   243  			parentNum := currBlockNumber - 1
   244  			parentBigInt := new(big.Int).Sub(currentBigInt, big.NewInt(1))
   245  			parentHash := currentBlock.ParentHash()
   246  			blockArr = append(blockArr, currentBlock)
   247  
   248  			currBlockNumber = parentNum
   249  			currentBigInt = parentBigInt
   250  			currBlockHash = parentHash
   251  			currentBlock = blockChain.GetBlock(currBlockHash, currBlockNumber)
   252  			count ++
   253  
   254  		}
   255  
   256  		for i := len(blockArr) - 1; 0 <= i; i-- {
   257  			currentBlock := blockArr[i]
   258  			currentNum := currentBlock.NumberU64()
   259  			currentBigInt := currentBlock.Number()
   260  			currentHash := currentBlock.Hash()
   261  
   262  			parentNum := currentNum - 1
   263  			//parentBigInt := new(big.Int).Sub(currentBigInt, big.NewInt(1))
   264  			parentHash := currentBlock.ParentHash()
   265  
   266  			// Special processing of the last block of the array, that is,
   267  			// the highest block pushes the BaseIrrCount block forward
   268  			if i == len(blockArr) - 1 && currentNum > 1  {
   269  
   270  				var /*parent,*/ current *state.StateDB
   271  
   272  				// parentStateDB by block
   273  				/*parentStateRoot := blockChain.GetBlock(parentHash, parentNum).Root()
   274  				log.Debug("Reload the oldest block at startup", "parentNum", parentNum, "parentHash", parentHash, "parentStateRoot", parentStateRoot.String())
   275  				if parentState, err := blockChain.StateAt(parentStateRoot, parentBigInt, parentHash); nil != err {
   276  					log.Error("Failed to load parentStateDB by block", "currtenNum", currentNum, "Hash", currentHash.String(), "parentNum", parentNum, "Hash", parentHash.String(), "err", err)
   277  					panic("Failed to load parentStateDB by block parentNum" + fmt.Sprint(parentNum) + ", Hash" + parentHash.String() + "err" + err.Error())
   278  				}else {
   279  					parent = parentState
   280  				}*/
   281  
   282  				// currentStateDB by block
   283  				stateRoot := blockChain.GetBlock(currentHash, currentNum).Root()
   284  				log.Debug("Reload the oldest block at startup", "currentNum", currentNum, "currentHash", currentHash, "stateRoot", stateRoot.String())
   285  				if currntState, err := blockChain.StateAt(stateRoot, currentBigInt, currentHash); nil != err {
   286  					log.Error("Failed to load currentStateDB by block", "currtenNum", currentNum, "Hash", currentHash.String(), "err", err)
   287  					panic("Failed to load currentStateDB by block currentNum" + fmt.Sprint(currentNum) + ", Hash" + currentHash.String() + "err" + err.Error())
   288  				}else {
   289  					current = currntState
   290  				}
   291  
   292  				if err := p.setEarliestIrrNodeCache(/*parent,*/ current, genesis.NumberU64(), currentNum, genesis.Hash(), currentHash); nil != err {
   293  					log.Error("Failed to setEarliestIrrNodeCache", "currentNum", currentNum, "Hash", currentHash.String(), "err", err)
   294  					panic("Failed to setEarliestIrrNodeCache currentNum" + fmt.Sprint(currentNum) + ", Hash" + currentHash.String() + "err" + err.Error())
   295  				}
   296  				continue
   297  			}
   298  
   299  			// stateDB by block
   300  			stateRoot := blockChain.GetBlock(currentHash, currentNum).Root()
   301  			log.Debug("Reload the front normal fast at startup", "currentNum", currentNum, "currentHash", currentHash, "stateRoot", stateRoot.String())
   302  			if currntState, err := blockChain.StateAt(stateRoot, currentBigInt, currentHash); nil != err {
   303  				log.Error("Failed to load stateDB by block", "currentNum", currentNum, "Hash", currentHash.String(), "err", err)
   304  				panic("Failed to load stateDB by block currentNum" + fmt.Sprint(currentNum) + ", Hash" + currentHash.String() + "err" + err.Error())
   305  			}else {
   306  				if err := p.setGeneralNodeCache(currntState, genesis.NumberU64(), parentNum, currentNum, genesis.Hash(), parentHash, currentHash); nil != err {
   307  					log.Error("Failed to setGeneralNodeCache", "currentNum", currentNum, "Hash", currentHash.String(), "err", err)
   308  					panic("Failed to setGeneralNodeCache currentNum" + fmt.Sprint(currentNum) + ", Hash" + currentHash.String() + "err" + err.Error())
   309  				}
   310  			}
   311  		}
   312  	}
   313  }
   314  
   315  
   316  func (p *ppos)buildGenesisRound(blockNumber uint64, blockHash common.Hash, initialNodes []discover.Node) {
   317  	initNodeArr := make([]*discover.Node, 0, len(initialNodes))
   318  	initialNodesIDs := make([]discover.NodeID, 0, len(initialNodes))
   319  	for _, n := range initialNodes {
   320  		node := n
   321  		initialNodesIDs = append(initialNodesIDs, node.ID)
   322  		initNodeArr = append(initNodeArr, &node)
   323  	}
   324  
   325  	// previous round
   326  	formerRound := &pposRound{
   327  		nodeIds: make([]discover.NodeID, 0),
   328  		nodes: 	make([]*discover.Node, 0),
   329  		start: big.NewInt(0),
   330  		end:   big.NewInt(0),
   331  	}
   332  
   333  	// current round
   334  	currentRound := &pposRound{
   335  		nodeIds: initialNodesIDs,
   336  		start: big.NewInt(1),
   337  		end:   big.NewInt(common.BaseSwitchWitness),
   338  	}
   339  
   340  	currentRound.nodes = make([]*discover.Node, len(initNodeArr))
   341  	copy(currentRound.nodes, initNodeArr)
   342  
   343  
   344  	log.Debug("Initialize ppos according to the configuration file:", "blockNumber", blockNumber, "blockHash", blockHash.String(), "start", currentRound.start, "end", currentRound.end)
   345  
   346  	node := &nodeCache{
   347  		former: 	formerRound,
   348  		current: 	currentRound,
   349  	}
   350  	res := make(roundCache, 0)
   351  	hashRound := make(map[common.Hash]*nodeCache, 0)
   352  	hashRound[blockHash] = node
   353  	res[blockNumber] = hashRound
   354  	/* set nodeRound ... */
   355  	p.nodeRound = res
   356  }
   357  
   358  func (p *ppos)printMapInfo(title string, blockNumber uint64, blockHash common.Hash){
   359  	res := p.nodeRound[blockNumber]
   360  
   361  	log.Debug(title + ":Traversing out the RoundNodes,num: " + fmt.Sprint(blockNumber) + ", hash: " + blockHash.String())
   362  
   363  	if round, ok  := res[blockHash]; ok {
   364  		if nil != round.former{
   365  			pposm.PrintObject(title + ":Traversing out of the round,num: " + fmt.Sprint(blockNumber) + ", hash: " + blockHash.String() + ", previous round: start:" + round.former.start.String() + ", end:" + round.former.end.String() + ", nodes: ", round.former.nodes)
   366  		}
   367  		if nil != round.current {
   368  			pposm.PrintObject(title + ":Traversing out of the round,num: " + fmt.Sprint(blockNumber) + ", hash: " + blockHash.String() + ", current round: start:" + round.current.start.String() + ", end:" + round.current.end.String() + ", nodes: ", round.current.nodes)
   369  		}
   370  		if nil != round.next {
   371  			pposm.PrintObject(title + ":Traversing out of the round,num: " + fmt.Sprint(blockNumber) + ", hash: " + blockHash.String() + ", next round: start:" + round.next.start.String() + ", end:" + round.next.end.String() + ", nodes: ", round.next.nodes)
   372  		}
   373  	}else {
   374  		log.Error(title + ":Traversing out of the round is NOT EXIST !!!!!!!!,num: " + fmt.Sprint(blockNumber) + ", hash: " + blockHash.String())
   375  	}
   376  }
   377  
   378  /** Method provided to the built-in contract call */
   379  // pledge Candidate
   380  func (p *ppos) SetCandidate(state vm.StateDB, nodeId discover.NodeID, can *types.Candidate) error {
   381  	return p.candidateContext.SetCandidate(state, nodeId, can)
   382  }
   383  
   384  // Getting immediate or reserve candidate info by nodeId
   385  func (p *ppos) GetCandidate(state vm.StateDB, nodeId discover.NodeID, blockNumber *big.Int) *types.Candidate {
   386  	return p.candidateContext.GetCandidate(state, nodeId, blockNumber)
   387  }
   388  
   389  // Getting immediate or reserve candidate info arr by nodeIds
   390  func (p *ppos) GetCandidateArr (state vm.StateDB, blockNumber *big.Int, nodeIds ... discover.NodeID) types.CandidateQueue {
   391  	return p.candidateContext.GetCandidateArr(state, blockNumber, nodeIds...)
   392  }
   393  
   394  // candidate withdraw from  elected candidates
   395  func (p *ppos) WithdrawCandidate(state vm.StateDB, nodeId discover.NodeID, price, blockNumber *big.Int) error {
   396  	return p.candidateContext.WithdrawCandidate(state, nodeId, price, blockNumber)
   397  }
   398  
   399  // Getting all  elected candidates array
   400  func (p *ppos) GetChosens(state vm.StateDB, flag int, blockNumber *big.Int) types.KindCanQueue {
   401  	return p.candidateContext.GetChosens(state, flag, blockNumber)
   402  }
   403  
   404  func (p *ppos) GetCandidatePendArr (state vm.StateDB, flag int, blockNumber *big.Int) types.CandidateQueue {
   405  	return p.candidateContext.GetCandidatePendArr(state, flag,  blockNumber)
   406  }
   407  
   408  // Getting all witness array
   409  func (p *ppos) GetChairpersons(state vm.StateDB, blockNumber *big.Int) []*types.Candidate {
   410  	return p.candidateContext.GetChairpersons(state, blockNumber)
   411  }
   412  
   413  // Getting all refund array by nodeId
   414  func (p *ppos) GetDefeat(state vm.StateDB, nodeId discover.NodeID, blockNumber *big.Int) types.RefundQueue {
   415  	return p.candidateContext.GetDefeat(state, nodeId, blockNumber)
   416  }
   417  
   418  // Checked current candidate was defeat by nodeId
   419  func (p *ppos) IsDefeat(state vm.StateDB, nodeId discover.NodeID, blockNumber *big.Int) bool {
   420  	return p.candidateContext.IsDefeat(state, nodeId, blockNumber)
   421  }
   422  
   423  // refund once
   424  func (p *ppos) RefundBalance(state vm.StateDB, nodeId discover.NodeID, blockNumber *big.Int) error {
   425  	return p.candidateContext.RefundBalance(state, nodeId, blockNumber)
   426  }
   427  
   428  // Getting owner's address of candidate info by nodeId
   429  func (p *ppos) GetOwner(state vm.StateDB, nodeId discover.NodeID, blockNumber *big.Int) common.Address {
   430  	return p.candidateContext.GetOwner(state, nodeId, blockNumber)
   431  }
   432  
   433  // Getting allow block interval for refunds
   434  func (p *ppos) GetRefundInterval(blockNumber *big.Int) uint32 {
   435  	return p.candidateContext.GetRefundInterval(blockNumber)
   436  }
   437  
   438  
   439  
   440  /** about ticketpool's method */
   441  
   442  func (p *ppos) GetPoolNumber (state vm.StateDB) uint32 {
   443  	return p.ticketContext.GetPoolNumber(state)
   444  }
   445  
   446  func (p *ppos) VoteTicket (state vm.StateDB, owner common.Address, voteNumber uint32, deposit *big.Int, nodeId discover.NodeID, blockNumber *big.Int) (uint32, error) {
   447  	return p.ticketContext.VoteTicket(state, owner, voteNumber, deposit, nodeId, blockNumber)
   448  }
   449  
   450  func (d *ppos) GetTicket(state vm.StateDB, ticketId common.Hash) *types.Ticket {
   451  	return d.ticketContext.GetTicket(state, ticketId)
   452  }
   453  
   454  func (p *ppos) GetTicketList (state vm.StateDB, ticketIds []common.Hash) []*types.Ticket {
   455  	return p.ticketContext.GetTicketList(state, ticketIds)
   456  }
   457  
   458  func (p *ppos) GetCandidateTicketIds (state vm.StateDB, nodeId discover.NodeID) []common.Hash {
   459  	return p.ticketContext.GetCandidateTicketIds(state, nodeId)
   460  }
   461  
   462  func (p *ppos) GetCandidateEpoch (state vm.StateDB, nodeId discover.NodeID) uint64 {
   463  	return p.ticketContext.GetCandidateEpoch(state, nodeId)
   464  }
   465  
   466  func (p *ppos) GetTicketPrice (state vm.StateDB) *big.Int {
   467  	return p.ticketContext.GetTicketPrice(state)
   468  }
   469  
   470  func (p *ppos) Notify (state vm.StateDB, blockNumber *big.Int) error {
   471  	return p.ticketContext.Notify(state, blockNumber)
   472  }
   473  
   474  func (p *ppos) StoreHash (state *state.StateDB, blockNumber *big.Int, blockHash common.Hash) {
   475  	if err := p.ticketContext.StoreHash(state, blockNumber, blockHash); nil != err {
   476  		log.Error("Failed to StoreHash", "err", err)
   477  		panic("Failed to StoreHash err" + err.Error())
   478  	}
   479  }
   480  
   481  func (p *ppos) Submit2Cache (state *state.StateDB, currBlocknumber,  blockInterval *big.Int, currBlockhash common.Hash) {
   482  	p.pposTemp.SubmitPposCache2Temp(currBlocknumber,  blockInterval, currBlockhash, state.SnapShotPPOSCache())
   483  }
   484  
   485  // cbft consensus fork need to update  nodeRound
   486  func (p *ppos) UpdateNodeList(blockChain *core.BlockChain, blocknumber *big.Int, blockHash common.Hash) {
   487  	log.Info("---cbft consensus fork,update nodeRound---")
   488  	// clean nodeCache
   489  	p.cleanNodeRound()
   490  
   491  
   492  	var curBlockNumber uint64 = blocknumber.Uint64()
   493  	var curBlockHash common.Hash = blockHash
   494  
   495  	currentBlock := blockChain.GetBlock(curBlockHash, curBlockNumber)
   496  	genesis := blockChain.Genesis()
   497  	p.lock.Lock()
   498  	defer p.lock.Unlock()
   499  
   500  	count := 0
   501  	blockArr := make([]*types.Block, 0)
   502  	for {
   503  		if curBlockNumber == genesis.NumberU64() || count == common.BaseIrrCount {
   504  			break
   505  		}
   506  		parentNum := curBlockNumber - 1
   507  		parentHash := currentBlock.ParentHash()
   508  		blockArr = append(blockArr, currentBlock)
   509  
   510  		curBlockNumber = parentNum
   511  		curBlockHash = parentHash
   512  		currentBlock = blockChain.GetBlock(curBlockHash, curBlockNumber)
   513  		count ++
   514  
   515  	}
   516  
   517  	for i := len(blockArr) - 1; 0 <= i; i-- {
   518  		currentBlock := blockArr[i]
   519  		currentNum := currentBlock.NumberU64()
   520  		currentBigInt := currentBlock.Number()
   521  		currentHash := currentBlock.Hash()
   522  
   523  		parentNum := currentNum - 1
   524  		//parentBigInt := new(big.Int).Sub(currentBigInt, big.NewInt(1))
   525  		parentHash := currentBlock.ParentHash()
   526  
   527  
   528  		// Special processing of the last block of the array, that is,
   529  		// the highest block pushes the BaseIrrCount block forward
   530  		if i == len(blockArr) - 1 && currentNum > 1  {
   531  
   532  			var/* parent,*/ current *state.StateDB
   533  
   534  			/*// parentStateDB by block
   535  			parentStateRoot := blockChain.GetBlock(parentHash, parentNum).Root()
   536  			if parentState, err := blockChain.StateAt(parentStateRoot, parentBigInt, parentHash); nil != err {
   537  				log.Error("Failed to load parentStateDB by block", "currtenNum", currentNum, "Hash", currentHash.String(), "parentNum", parentNum, "Hash", parentHash.String(), "err", err)
   538  				panic("Failed to load parentStateDB by block parentNum" + fmt.Sprint(parentNum) + ", Hash" + parentHash.String() + "err" + err.Error())
   539  			}else {
   540  				parent = parentState
   541  			}*/
   542  
   543  			// currentStateDB by block
   544  			stateRoot := blockChain.GetBlock(currentHash, currentNum).Root()
   545  			if currntState, err := blockChain.StateAt(stateRoot, currentBigInt, currentHash); nil != err {
   546  				log.Error("Failed to load currentStateDB by block", "currentNum", currentNum, "Hash", currentHash.String(), "err", err)
   547  				panic("Failed to load currentStateDB by block currentNum" + fmt.Sprint(currentNum) + ", Hash" + currentHash.String() + "err" + err.Error())
   548  			}else {
   549  				current = currntState
   550  			}
   551  
   552  			if err := p.setEarliestIrrNodeCache(/*parent,*/ current, genesis.NumberU64(), currentNum, genesis.Hash(), currentHash); nil != err {
   553  				log.Error("Failed to setEarliestIrrNodeCache", "currentNum", currentNum, "Hash", currentHash.String(), "err", err)
   554  				panic("Failed to setEarliestIrrNodeCache currentNum" + fmt.Sprint(currentNum) + ", Hash" + currentHash.String() + "err" + err.Error())
   555  			}
   556  			p.printMapInfo("Reload the oldest block when forked", currentNum, currentHash)
   557  			continue
   558  		}
   559  
   560  		// stateDB by block
   561  		stateRoot := blockChain.GetBlock(currentHash, currentNum).Root()
   562  		if currntState, err := blockChain.StateAt(stateRoot, currentBigInt, currentHash); nil != err {
   563  			log.Error("Failed to load stateDB by block", "currentNum", currentNum, "Hash", currentHash.String(), "err", err)
   564  			panic("Failed to load stateDB by block currentNum" + fmt.Sprint(currentNum) + ", Hash" + currentHash.String() + "err" + err.Error())
   565  		}else {
   566  			if err := p.setGeneralNodeCache(currntState, genesis.NumberU64(), parentNum, currentNum, genesis.Hash(), parentHash, currentHash); nil != err {
   567  				log.Error("Failed to setGeneralNodeCache", "currentNum", currentNum, "Hash", currentHash.String(), "err", err)
   568  				panic("Failed to setGeneralNodeCache currentNum" + fmt.Sprint(currentNum) + ", Hash" + currentHash.String() + "err" + err.Error())
   569  			}
   570  		}
   571  		p.printMapInfo("Reload the previous normal block when forking", currentNum, currentHash)
   572  	}
   573  }
   574  
   575  func convertNodeID(nodes []*discover.Node) []discover.NodeID {
   576  	nodesID := make([]discover.NodeID, 0, len(nodes))
   577  	for _, n := range nodes {
   578  		nodesID = append(nodesID, n.ID)
   579  	}
   580  	return nodesID
   581  }
   582  
   583  // calculate current round number by current blocknumber
   584  func calcurround(blocknumber uint64) uint64 {
   585  	// current num
   586  	var round uint64
   587  	div := blocknumber / common.BaseSwitchWitness
   588  	mod := blocknumber % common.BaseSwitchWitness
   589  	if (div == 0 && mod == 0) || (div == 0 && mod > 0 && mod < common.BaseSwitchWitness) { // first round
   590  		round = 1
   591  	} else if div > 0 && mod == 0 {
   592  		round = div
   593  	} else if div > 0 && mod > 0 && mod < common.BaseSwitchWitness {
   594  		round = div + 1
   595  	}
   596  	return round
   597  }
   598  
   599  
   600  func (p *ppos) GetFormerRound(blockNumber *big.Int, blockHash common.Hash) *pposRound {
   601  	p.lock.RLock()
   602  	defer p.lock.RUnlock()
   603  	return p.nodeRound.getFormerRound(blockNumber, blockHash)
   604  }
   605  
   606  func (p *ppos) GetCurrentRound (blockNumber *big.Int, blockHash common.Hash) *pposRound {
   607  	p.lock.RLock()
   608  	defer p.lock.RUnlock()
   609  	return p.nodeRound.getCurrentRound(blockNumber, blockHash)
   610  }
   611  
   612  func (p *ppos)  GetNextRound (blockNumber *big.Int, blockHash common.Hash) *pposRound {
   613  	p.lock.RLock()
   614  	defer p.lock.RUnlock()
   615  	return p.nodeRound.getNextRound(blockNumber, blockHash)
   616  }
   617  
   618  func (p *ppos) SetNodeCache (state *state.StateDB, genesisNumber, parentNumber, currentNumber *big.Int, genesisHash, parentHash, currentHash common.Hash) error {
   619  	p.lock.Lock()
   620  	defer p.lock.Unlock()
   621  	return p.setGeneralNodeCache(state, genesisNumber.Uint64(), parentNumber.Uint64(), currentNumber.Uint64(), genesisHash, parentHash, currentHash)
   622  }
   623  func (p *ppos) setGeneralNodeCache (state *state.StateDB, genesisNumber, parentNumber, currentNumber uint64, genesisHash, parentHash, currentHash common.Hash) error {
   624  	parentNumBigInt := big.NewInt(int64(parentNumber))
   625  	// current round
   626  	round := calcurround(currentNumber)
   627  
   628  	log.Debug("Setting current  block Node Cache", "parentNumber", parentNumber, "ParentHash", parentHash.String(), "currentNumber:", currentNumber, "hash", currentHash.String(), "round:", round)
   629  
   630  	/** ------------------------------ current ppos ------------------------------ **/
   631  	preNodes, curNodes, nextNodes, err := p.candidateContext.GetAllWitness(state, big.NewInt(int64(currentNumber)))
   632  
   633  	if nil != err {
   634  		log.Error("Failed to setting nodeCache on setGeneralNodeCache", "err", err)
   635  		return err
   636  	}
   637  
   638  	/** ------------------------------    parent    ------------------------------ **/
   639  
   640  	parent_Former_Round := p.nodeRound.getFormerRound(parentNumBigInt, parentHash)
   641  
   642  	parent_Current_Round := p.nodeRound.getCurrentRound(parentNumBigInt, parentHash)
   643  
   644  	parent_Next_Round := p.nodeRound.getNextRound(parentNumBigInt, parentHash)
   645  
   646  	/** ------------------------------    genesis    ------------------------------ **/
   647  
   648  	genesisNumBigInt := big.NewInt(int64(genesisNumber))
   649  	genesis_Current_Round := p.nodeRound.getCurrentRound(genesisNumBigInt, genesisHash)
   650  
   651  	/** ------------------------------       end       ---------------------------- **/
   652  
   653  	var start, end *big.Int
   654  
   655  	// Determine if it is the last block of the current round.
   656  	// If it is, start is the start of the next round,
   657  	// and end is the end of the next round.
   658  	if cmpSwitch(round, currentNumber) == 0 {
   659  		start = big.NewInt(int64(common.BaseSwitchWitness*round) + 1)
   660  		end = new(big.Int).Add(start, big.NewInt(int64(common.BaseSwitchWitness-1)))
   661  	}else {
   662  		start = big.NewInt(int64(common.BaseSwitchWitness*(round-1)) + 1)
   663  		end = new(big.Int).Add(start, big.NewInt(int64(common.BaseSwitchWitness-1)))
   664  	}
   665  
   666  	// former
   667  	formerRound := &pposRound{}
   668  	// former start, end
   669  	if round != common.FirstRound {
   670  		formerRound.start = new(big.Int).Sub(start, new(big.Int).SetUint64(uint64(common.BaseSwitchWitness)))
   671  		formerRound.end = new(big.Int).Sub(end, new(big.Int).SetUint64(uint64(common.BaseSwitchWitness)))
   672  	}else {
   673  		formerRound.start = big.NewInt(0)
   674  		formerRound.end = big.NewInt(0)
   675  	}
   676  
   677  	log.Debug("Setting current  block Node Cache Previous round ", "start",formerRound.start, "end", formerRound.end)
   678  
   679  	if len(preNodes) != 0 {
   680  		formerRound.nodeIds = convertNodeID(preNodes)
   681  		formerRound.nodes = make([]*discover.Node, len(preNodes))
   682  		copy(formerRound.nodes, preNodes)
   683  	}else { // Reference parent
   684  		// if last block of round
   685  		if cmpSwitch(round, currentNumber) == 0 {
   686  			//parentCurRound := p.nodeRound.getCurrentRound(parentNumBigInt, parentHash)
   687  			if nil != parent_Current_Round {
   688  				formerRound.nodeIds = make([]discover.NodeID, len(parent_Current_Round.nodeIds))
   689  				copy(formerRound.nodeIds, parent_Current_Round.nodeIds)
   690  				formerRound.nodes = make([]*discover.Node, len(parent_Current_Round.nodes))
   691  				copy(formerRound.nodes, parent_Current_Round.nodes)
   692  			}else {
   693  				formerRound.nodeIds = make([]discover.NodeID, len(genesis_Current_Round.nodeIds))
   694  				copy(formerRound.nodeIds, genesis_Current_Round.nodeIds)
   695  				formerRound.nodes = make([]*discover.Node, len(genesis_Current_Round.nodes))
   696  				copy(formerRound.nodes, genesis_Current_Round.nodes)
   697  			}
   698  		}else { // Is'nt last block of round
   699  			//parentFormerRound := p.nodeRound.getFormerRound(parentNumBigInt, parentHash)
   700  			if nil != parent_Former_Round {
   701  				formerRound.nodeIds = make([]discover.NodeID, len(parent_Former_Round.nodeIds))
   702  				copy(formerRound.nodeIds, parent_Former_Round.nodeIds)
   703  				formerRound.nodes = make([]*discover.Node, len(parent_Former_Round.nodes))
   704  				copy(formerRound.nodes, parent_Former_Round.nodes)
   705  			}else {
   706  				formerRound.nodeIds = make([]discover.NodeID, len(genesis_Current_Round.nodeIds))
   707  				copy(formerRound.nodeIds, genesis_Current_Round.nodeIds)
   708  				formerRound.nodes = make([]*discover.Node, len(genesis_Current_Round.nodes))
   709  				copy(formerRound.nodes, genesis_Current_Round.nodes)
   710  			}
   711  		}
   712  	}
   713  
   714  	// current
   715  	currentRound := &pposRound{}
   716  	// current start, end
   717  	currentRound.start = start
   718  	currentRound.end = end
   719  
   720  	log.Debug("Setting current  block Node Cache Current round ", "start", currentRound.start, "end",currentRound.end)
   721  
   722  	if len(curNodes) != 0 {
   723  		currentRound.nodeIds = convertNodeID(curNodes)
   724  		currentRound.nodes = make([]*discover.Node, len(curNodes))
   725  		copy(currentRound.nodes, curNodes)
   726  	}else { // Reference parent
   727  		// if last block of round
   728  		if cmpSwitch(round, currentNumber) == 0 {
   729  			//parentNextRound := p.nodeRound.getNextRound(parentNumBigInt, parentHash)
   730  			if nil != parent_Next_Round {
   731  				currentRound.nodeIds = make([]discover.NodeID, len(parent_Next_Round.nodeIds))
   732  				copy(currentRound.nodeIds, parent_Next_Round.nodeIds)
   733  				currentRound.nodes = make([]*discover.Node, len(parent_Next_Round.nodes))
   734  				copy(currentRound.nodes, parent_Next_Round.nodes)
   735  			}else {
   736  				currentRound.nodeIds = make([]discover.NodeID, len(genesis_Current_Round.nodeIds))
   737  				copy(currentRound.nodeIds, genesis_Current_Round.nodeIds)
   738  				currentRound.nodes = make([]*discover.Node, len(genesis_Current_Round.nodes))
   739  				copy(currentRound.nodes, genesis_Current_Round.nodes)
   740  			}
   741  
   742  		}else { // Is'nt last block of round
   743  			//parentCurRound := p.nodeRound.getCurrentRound(parentNumBigInt, parentHash)
   744  			if nil != parent_Current_Round {
   745  				currentRound.nodeIds = make([]discover.NodeID, len(parent_Current_Round.nodeIds))
   746  				copy(currentRound.nodeIds, parent_Current_Round.nodeIds)
   747  				currentRound.nodes = make([]*discover.Node, len(parent_Current_Round.nodes))
   748  				copy(currentRound.nodes, parent_Current_Round.nodes)
   749  			}else {
   750  				currentRound.nodeIds = make([]discover.NodeID, len(genesis_Current_Round.nodeIds))
   751  				copy(currentRound.nodeIds, genesis_Current_Round.nodeIds)
   752  				currentRound.nodes = make([]*discover.Node, len(genesis_Current_Round.nodes))
   753  				copy(currentRound.nodes, genesis_Current_Round.nodes)
   754  			}
   755  		}
   756  	}
   757  
   758  
   759  	// next
   760  	nextRound := &pposRound{}
   761  	// next start, end
   762  	nextRound.start = new(big.Int).Add(start, new(big.Int).SetUint64(uint64(common.BaseSwitchWitness)))
   763  	nextRound.end = new(big.Int).Add(end, new(big.Int).SetUint64(uint64(common.BaseSwitchWitness)))
   764  
   765  	log.Debug("Setting current  block Node Cache Next round ", "start", nextRound.start, "end",nextRound.end)
   766  
   767  	if len(nextNodes) != 0 {
   768  		nextRound.nodeIds = convertNodeID(nextNodes)
   769  		nextRound.nodes = make([]*discover.Node, len(nextNodes))
   770  		copy(nextRound.nodes, nextNodes)
   771  	}else { // Reference parent
   772  
   773  		if cmpElection(round, currentNumber) == 0  { // election index == cur index
   774  			//parentCurRound := p.nodeRound.getCurrentRound(parentNumBigInt, parentHash)
   775  			if nil != parent_Current_Round {
   776  				nextRound.nodeIds = make([]discover.NodeID, len(parent_Current_Round.nodeIds))
   777  				copy(nextRound.nodeIds, parent_Current_Round.nodeIds)
   778  				nextRound.nodes = make([]*discover.Node, len(parent_Current_Round.nodes))
   779  				copy(nextRound.nodes, parent_Current_Round.nodes)
   780  			}else {
   781  				nextRound.nodeIds = make([]discover.NodeID, len(genesis_Current_Round.nodeIds))
   782  				copy(nextRound.nodeIds, genesis_Current_Round.nodeIds)
   783  				nextRound.nodes = make([]*discover.Node, len(genesis_Current_Round.nodes))
   784  				copy(nextRound.nodes, genesis_Current_Round.nodes)
   785  			}
   786  		}else if cmpElection(round, currentNumber) > 0  &&  cmpSwitch(round, currentNumber) < 0 {  // election index < cur index < switch index
   787  			//parentNextRound := p.nodeRound.getNextRound(parentNumBigInt, parentHash)
   788  			if nil != parent_Next_Round {
   789  				nextRound.nodeIds = make([]discover.NodeID, len(parent_Next_Round.nodeIds))
   790  				copy(nextRound.nodeIds, parent_Next_Round.nodeIds)
   791  				nextRound.nodes = make([]*discover.Node, len(parent_Next_Round.nodes))
   792  				copy(nextRound.nodes, parent_Next_Round.nodes)
   793  			}else {
   794  				nextRound.nodeIds = make([]discover.NodeID, len(genesis_Current_Round.nodeIds))
   795  				copy(nextRound.nodeIds, genesis_Current_Round.nodeIds)
   796  				nextRound.nodes = make([]*discover.Node, len(genesis_Current_Round.nodes))
   797  				copy(nextRound.nodes, genesis_Current_Round.nodes)
   798  			}
   799  		}else { // switch index <= cur index < next election index
   800  			nextRound.nodeIds = make([]discover.NodeID, 0)
   801  			nextRound.nodes = make([]*discover.Node, 0)
   802  		}
   803  	}
   804  
   805  	cache := &nodeCache{
   806  		former: 	formerRound,
   807  		current: 	currentRound,
   808  		next: 		nextRound,
   809  	}
   810  	p.nodeRound.setNodeCache(big.NewInt(int64(currentNumber)), currentHash, cache)
   811  
   812  	log.Debug("When setting the information of the current block", "currentBlockNum", currentNumber, "parentNum", parentNumber, "currentHash", currentHash.String(), "parentHash", parentHash.String())
   813  	p.printMapInfo("When setting the information of the current block", currentNumber, currentHash)
   814  
   815  	return nil
   816  }
   817  
   818  func (p *ppos) setEarliestIrrNodeCache (/*parentState, */currentState *state.StateDB, genesisNumber, currentNumber uint64, genesisHash, currentHash common.Hash) error {
   819  	genesisNumBigInt := big.NewInt(int64(genesisNumber))
   820  	// current round
   821  	round := calcurround(currentNumber)
   822  	log.Debug("Set the farthest allowed cache reserved block", "currentNumber:", currentNumber, "round:", round)
   823  
   824  	curr_PRE_Nodes, curr_CURR_Nodes, curr_NEXT_Nodes, err := p.candidateContext.GetAllWitness(currentState, big.NewInt(int64(currentNumber)))
   825  
   826  	if nil != err {
   827  		log.Error("Failed to setting nodeCache by currentStateDB on setEarliestIrrNodeCache", "err", err)
   828  		return err
   829  	}
   830  
   831  	/*parent_preNodes, parent_curNodes, parent_nextNodes, err := p.candidateContext.GetAllWitness(parentState)
   832  	if nil != err {
   833  		log.Error("Failed to setting nodeCache by parentStateDB on setEarliestIrrNodeCache", "err", err)
   834  		return err
   835  	}*/
   836  
   837  	genesisCurRound := p.nodeRound.getCurrentRound(genesisNumBigInt, genesisHash)
   838  
   839  	var start, end *big.Int
   840  
   841  	/**
   842  	Determine if it is the last block of the current round.
   843  	If it is, start is the start of the next round,
   844  	and end is the end of the next round.
   845  	*/
   846  	if cmpSwitch(round, currentNumber) == 0 {
   847  		start = big.NewInt(int64(common.BaseSwitchWitness*round) + 1)
   848  		end = new(big.Int).Add(start, big.NewInt(int64(common.BaseSwitchWitness-1)))
   849  	}else {
   850  		start = big.NewInt(int64(common.BaseSwitchWitness*(round-1)) + 1)
   851  		end = new(big.Int).Add(start, big.NewInt(int64(common.BaseSwitchWitness-1)))
   852  	}
   853  
   854  	/**
   855  	Sets former info
   856  	*/
   857  	formerRound := &pposRound{}
   858  	// former start, end
   859  	if round != common.FirstRound {
   860  		formerRound.start = new(big.Int).Sub(start, new(big.Int).SetUint64(uint64(common.BaseSwitchWitness)))
   861  		formerRound.end = new(big.Int).Sub(end, new(big.Int).SetUint64(uint64(common.BaseSwitchWitness)))
   862  	}else {
   863  		formerRound.start = big.NewInt(0)
   864  		formerRound.end = big.NewInt(0)
   865  	}
   866  
   867  	log.Debug("Set the farthest allowed cache reserved block: Previous round ", "start",formerRound.start, "end", formerRound.end)
   868  
   869  	// sets previous
   870  	if len(curr_PRE_Nodes) != 0 {
   871  		formerRound.nodeIds = convertNodeID(curr_PRE_Nodes)
   872  		formerRound.nodes = make([]*discover.Node, len(curr_PRE_Nodes))
   873  		copy(formerRound.nodes, curr_PRE_Nodes)
   874  	}else {
   875  		// Reference parent
   876  		// if last block of roundcurrentState
   877  		if cmpSwitch(round, currentNumber) == 0 {
   878  			// First take the stateDB from the previous block,
   879  			// the stateDB of the previous block is not,
   880  			// just take the nodeCache corresponding to the creation block.
   881  			/*if len(parent_curNodes) != 0 {
   882  				//formerRound.nodeIds = make([]discover.NodeID, len(parent_curNodes))
   883  				formerRound.nodeIds = convertNodeID(parent_curNodes)
   884  				formerRound.nodes = make([]*discover.Node, len(parent_curNodes))
   885  				copy(formerRound.nodes, parent_curNodes)
   886  			}else {
   887  				if nil != genesisCurRound {
   888  					formerRound.nodeIds = make([]discover.NodeID, len(genesisCurRound.nodeIds))
   889  					copy(formerRound.nodeIds, genesisCurRound.nodeIds)
   890  					formerRound.nodes = make([]*discover.Node, len(genesisCurRound.nodes))
   891  					copy(formerRound.nodes, genesisCurRound.nodes)
   892  				}
   893  			}*/
   894  
   895  			if nil != genesisCurRound {
   896  				formerRound.nodeIds = make([]discover.NodeID, len(genesisCurRound.nodeIds))
   897  				copy(formerRound.nodeIds, genesisCurRound.nodeIds)
   898  				formerRound.nodes = make([]*discover.Node, len(genesisCurRound.nodes))
   899  				copy(formerRound.nodes, genesisCurRound.nodes)
   900  			}
   901  
   902  		}else { // Is'nt last block of round
   903  
   904  			/*if len(parent_preNodes) != 0 {
   905  				//formerRound.nodeIds = make([]discover.NodeID, len(parent_preNodes))
   906  				formerRound.nodeIds = convertNodeID(parent_preNodes)
   907  				formerRound.nodes = make([]*discover.Node, len(parent_preNodes))
   908  				copy(formerRound.nodes, parent_preNodes)
   909  			}else {
   910  				if  nil != genesisCurRound {
   911  					formerRound.nodeIds = make([]discover.NodeID, len(genesisCurRound.nodeIds))
   912  					copy(formerRound.nodeIds, genesisCurRound.nodeIds)
   913  					formerRound.nodes = make([]*discover.Node, len(genesisCurRound.nodes))
   914  					copy(formerRound.nodes, genesisCurRound.nodes)
   915  				}
   916  			}*/
   917  
   918  			if  nil != genesisCurRound {
   919  				formerRound.nodeIds = make([]discover.NodeID, len(genesisCurRound.nodeIds))
   920  				copy(formerRound.nodeIds, genesisCurRound.nodeIds)
   921  				formerRound.nodes = make([]*discover.Node, len(genesisCurRound.nodes))
   922  				copy(formerRound.nodes, genesisCurRound.nodes)
   923  			}
   924  
   925  		}
   926  	}
   927  
   928  	/**
   929  	Sets current info
   930  	*/
   931  	currentRound := &pposRound{}
   932  	// current start, end
   933  	currentRound.start = start
   934  	currentRound.end = end
   935  
   936  	log.Debug("Set the farthest allowed cache reserved block: Current round", "start", currentRound.start, "end",currentRound.end)
   937  
   938  	// sets current
   939  	if len(curr_CURR_Nodes) != 0 {
   940  		currentRound.nodeIds = convertNodeID(curr_CURR_Nodes)
   941  		currentRound.nodes = make([]*discover.Node, len(curr_CURR_Nodes))
   942  		copy(currentRound.nodes, curr_CURR_Nodes)
   943  	}else { // Reference parent
   944  		// if last block of round
   945  		if cmpSwitch(round, currentNumber) == 0 {
   946  			/*if len(parent_nextNodes) != 0  {
   947  				currentRound.nodeIds = convertNodeID(parent_nextNodes)
   948  				currentRound.nodes = make([]*discover.Node, len(parent_nextNodes))
   949  				copy(currentRound.nodes, parent_nextNodes)
   950  			}else {
   951  				if  nil != genesisCurRound {
   952  					currentRound.nodeIds = make([]discover.NodeID, len(genesisCurRound.nodeIds))
   953  					copy(currentRound.nodeIds, genesisCurRound.nodeIds)
   954  					currentRound.nodes = make([]*discover.Node, len(genesisCurRound.nodes))
   955  					copy(currentRound.nodes, genesisCurRound.nodes)
   956  				}
   957  			}*/
   958  
   959  			if  nil != genesisCurRound {
   960  				currentRound.nodeIds = make([]discover.NodeID, len(genesisCurRound.nodeIds))
   961  				copy(currentRound.nodeIds, genesisCurRound.nodeIds)
   962  				currentRound.nodes = make([]*discover.Node, len(genesisCurRound.nodes))
   963  				copy(currentRound.nodes, genesisCurRound.nodes)
   964  			}
   965  		}else { // Is'nt last block of round
   966  
   967  			/*if len(parent_curNodes) != 0 {
   968  				currentRound.nodeIds = convertNodeID(parent_curNodes)
   969  				currentRound.nodes = make([]*discover.Node, len(parent_curNodes))
   970  				copy(currentRound.nodes, parent_curNodes)
   971  			}else {
   972  				if  nil != genesisCurRound {
   973  					currentRound.nodeIds = make([]discover.NodeID, len(genesisCurRound.nodeIds))
   974  					copy(currentRound.nodeIds, genesisCurRound.nodeIds)
   975  					currentRound.nodes = make([]*discover.Node, len(genesisCurRound.nodes))
   976  					copy(currentRound.nodes, genesisCurRound.nodes)
   977  				}
   978  			}*/
   979  
   980  			if  nil != genesisCurRound {
   981  				currentRound.nodeIds = make([]discover.NodeID, len(genesisCurRound.nodeIds))
   982  				copy(currentRound.nodeIds, genesisCurRound.nodeIds)
   983  				currentRound.nodes = make([]*discover.Node, len(genesisCurRound.nodes))
   984  				copy(currentRound.nodes, genesisCurRound.nodes)
   985  			}
   986  
   987  		}
   988  	}
   989  
   990  	/**
   991  	Sets next info
   992  	*/
   993  	nextRound := &pposRound{}
   994  	// next start, end
   995  	nextRound.start = new(big.Int).Add(start, new(big.Int).SetUint64(uint64(common.BaseSwitchWitness)))
   996  	nextRound.end = new(big.Int).Add(end, new(big.Int).SetUint64(uint64(common.BaseSwitchWitness)))
   997  
   998  	log.Debug("Set the farthest allowed cache reserved block: Next round", "start", nextRound.start, "end",nextRound.end)
   999  
  1000  	// sets next
  1001  	if len(curr_NEXT_Nodes) != 0 {
  1002  		nextRound.nodeIds = convertNodeID(curr_NEXT_Nodes)
  1003  		nextRound.nodes = make([]*discover.Node, len(curr_NEXT_Nodes))
  1004  		copy(nextRound.nodes, curr_NEXT_Nodes)
  1005  	}else { // Reference parent
  1006  		// election index == cur index || election index < cur index < switch index
  1007  		if cmpElection(round, currentNumber) == 0 || (cmpElection(round, currentNumber) > 0 && cmpSwitch(round, currentNumber) < 0)  {
  1008  
  1009  			if nil != genesisCurRound {
  1010  				nextRound.nodeIds = make([]discover.NodeID, len(genesisCurRound.nodeIds))
  1011  				copy(nextRound.nodeIds, genesisCurRound.nodeIds)
  1012  				nextRound.nodes = make([]*discover.Node, len(genesisCurRound.nodes))
  1013  				copy(nextRound.nodes, genesisCurRound.nodes)
  1014  			}
  1015  		}else { // parent switch index <= cur index < election index  || switch index <= cur index < next election index
  1016  			nextRound.nodeIds = make([]discover.NodeID, 0)
  1017  			nextRound.nodes = make([]*discover.Node, 0)
  1018  		}
  1019  	}
  1020  
  1021  	/*
  1022  		Sets nodeCache
  1023  	*/
  1024  	cache := &nodeCache{
  1025  		former: 	formerRound,
  1026  		current: 	currentRound,
  1027  		next: 		nextRound,
  1028  	}
  1029  	p.nodeRound.setNodeCache(big.NewInt(int64(currentNumber)), currentHash, cache)
  1030  	log.Debug("Set the farthest allowed to cache the information of the reserved block", "currentBlockNum", currentNumber, "currentHash", currentHash.String())
  1031  	p.printMapInfo("Set the farthest allowed to cache the information of the reserved block", currentNumber, currentHash)
  1032  	return nil
  1033  }
  1034  
  1035  
  1036  func (p *ppos) cleanNodeRound () {
  1037  	p.lock.Lock()
  1038  	p.nodeRound =  make(roundCache, 0)
  1039  	p.lock.Unlock()
  1040  }
  1041  
  1042  // election index == cur       0
  1043  // cur < election index       -1
  1044  // election index < cur        1
  1045  // param invalid              -2
  1046  func cmpElection (round, currentNumber uint64) int {
  1047  	// last num of round
  1048  	last := int(round * common.BaseSwitchWitness)
  1049  	ele_sub := int(common.BaseSwitchWitness - common.BaseElection)
  1050  	curr_sub := last - int(currentNumber)
  1051  	sub := ele_sub - curr_sub
  1052  	//fmt.Println("sss ", sub)
  1053  	if curr_sub < int(0)  {
  1054  		return -2
  1055  	}else if sub > int(0) {
  1056  		return 1
  1057  	}else if sub == int(0) {
  1058  		return 0
  1059  	}else {
  1060  		return -1
  1061  	}
  1062  }
  1063  
  1064  // switch index == cur       0
  1065  // cur < switch index       -1
  1066  // switch index < cur        1
  1067  // param invalid            -2
  1068  func cmpSwitch (round, currentNum uint64) int {
  1069  	last := round * common.BaseSwitchWitness
  1070  	if last < currentNum {
  1071  		return 1
  1072  	}else if last == currentNum {
  1073  		return 0
  1074  	}else {
  1075  		return -1
  1076  	}
  1077  }
  1078  
  1079  func (p *ppos) setPPOS_Temp(){
  1080  	p.pposTemp = ppos_storage.GetPPosTempPtr()
  1081  }
  1082