github.com/cheng762/platon-go@v1.8.17-0.20190529111256-7deff2d7be26/core/ppos_storage/ppos_temp.go (about)

     1  package ppos_storage
     2  
     3  import (
     4  	"sync"
     5  	"math/big"
     6  	"github.com/PlatONnetwork/PlatON-Go/log"
     7  	"github.com/PlatONnetwork/PlatON-Go/common"
     8  
     9  	"github.com/PlatONnetwork/PlatON-Go/ethdb"
    10  	"github.com/golang/protobuf/proto"
    11  	"github.com/PlatONnetwork/PlatON-Go/core/types"
    12  	"errors"
    13  	"github.com/PlatONnetwork/PlatON-Go/p2p/discover"
    14  	"fmt"
    15  	"encoding/json"
    16  	"crypto/md5"
    17  )
    18  
    19  const ppos_empty_indb  = "leveldb: not found"
    20  
    21  var (
    22  	WRITE_PPOS_ERR = errors.New("Failed to Write ppos storage into disk")
    23  
    24  	// The key of ppos storage in disk (leveldb)
    25  	PPOS_STORAGE_KEY = []byte("PPOS_STORAGE_KEY")
    26  )
    27  
    28  type numTempMap map[string]hashTempMap
    29  type hashTempMap map[common.Hash]*Ppos_storage
    30  
    31  // Global PPOS Dependency TEMP
    32  type PPOS_TEMP struct {
    33  
    34  	BlockNumber 	*big.Int
    35  	BlockHash 		common.Hash
    36  
    37  	db ethdb.Database
    38  
    39  	// Record block total count
    40  	BlockCount 	uint32
    41  
    42  	// global data temp
    43  	TempMap numTempMap
    44  
    45  	lock  *sync.Mutex
    46  }
    47  
    48  /**
    49  This is a Global ppos data temp
    50   */
    51  var  ppos_temp *PPOS_TEMP
    52  
    53  
    54  func NewPPosTemp(db ethdb.Database) *PPOS_TEMP {
    55  
    56  	timer := common.NewTimer()
    57  	timer.Begin()
    58  
    59  	log.Info("NewPPosTemp start ...")
    60  	if nil != ppos_temp {
    61  		return ppos_temp
    62  	}
    63  	ppos_temp = new(PPOS_TEMP)
    64  
    65  	ppos_temp.db = db
    66  
    67  	ppos_temp.BlockCount = 0
    68  
    69  	ntemp := make(numTempMap, 0)
    70  	ppos_temp.TempMap = ntemp
    71  	ppos_temp.lock = &sync.Mutex{}
    72  
    73  	// defualt value
    74  	ppos_temp.BlockNumber = big.NewInt(0)
    75  	ppos_temp.BlockHash = common.Hash{}
    76  
    77  	if data, err := db.Get(PPOS_STORAGE_KEY); nil != err {
    78  		if ppos_empty_indb != err.Error() {
    79  			log.Error("Failed to Call NewPPosTemp to get Global ppos temp by levelDB", "err", err)
    80  			return ppos_temp
    81  		}
    82  	} else {
    83  		log.Debug("Call NewPPosTemp to Unmarshal Global ppos temp", "pb data len", len(data))
    84  
    85  		pb_pposTemp := new(PB_PPosTemp)
    86  		if err := proto.Unmarshal(data, pb_pposTemp); err != nil {
    87  			log.Error("Failed to Call NewPPosTemp to Unmarshal Global ppos temp", "err", err)
    88  			return ppos_temp
    89  		}else {
    90  			/**
    91  			build global ppos_temp
    92  			 */
    93  
    94  			 // TODO
    95  			log.Debug("NewPPosTemp  loading data from disk:", "data len", len(data), "dataMD5", md5.Sum(data))
    96  
    97  			//PrintObject("NewPPosTemp  loading data from disk:", pb_pposTemp)
    98  
    99  
   100  			pposStorage := unmarshalPBStorage(pb_pposTemp)
   101  
   102  
   103  			hashMap := make(map[common.Hash]*Ppos_storage, 0)
   104  			blockHash := common.HexToHash(pb_pposTemp.BlockHash)
   105  			hashMap[blockHash] = pposStorage
   106  			ppos_temp.TempMap[pb_pposTemp.BlockNumber] = hashMap
   107  
   108  			num, _ := new(big.Int).SetString(pb_pposTemp.BlockNumber, 10)
   109  
   110  			ppos_temp.BlockNumber = num
   111  			ppos_temp.BlockHash = blockHash
   112  
   113  			log.Debug("Call NewPPosTemp loading into memory data", "blockNumber", pb_pposTemp.BlockNumber, "blockHash", pb_pposTemp.BlockHash)
   114  
   115  		}
   116  	}
   117  
   118  	log.Debug("Call NewPPosTemp finish ...", "time long ms: ", timer.End())
   119  	return ppos_temp
   120  }
   121  
   122  func GetPPosTempPtr() *PPOS_TEMP {
   123  	return ppos_temp
   124  }
   125  
   126  
   127  func BuildPposCache(blockNumber *big.Int, blockHash common.Hash) *Ppos_storage {
   128  	return ppos_temp.getPposCacheFromTemp(blockNumber, blockHash)
   129  }
   130  
   131  
   132  // Get ppos storage cache by same block
   133  func (temp *PPOS_TEMP) getPposCacheFromTemp(blockNumber *big.Int, blockHash common.Hash) *Ppos_storage {
   134  
   135  	ppos_storage := NewPPOS_storage()
   136  
   137  	notGenesisBlock := blockNumber.Cmp(big.NewInt(0)) > 0
   138  
   139  	if nil == temp && notGenesisBlock {
   140  		log.Warn("Warn Call getPposCacheFromTemp of PPOS_TEMP, the Global PPOS_TEMP instance is nil !!!!!!!!!!!!!!!", "blockNumber", blockNumber.Uint64(), "blockHash", blockHash.Hex())
   141  		return ppos_storage
   142  	}
   143  
   144  	if !notGenesisBlock || (common.Hash{}) == blockHash {
   145  		return ppos_storage
   146  	}
   147  
   148  	var storage *Ppos_storage
   149  
   150  	temp.lock.Lock()
   151  	if hashTemp, ok := temp.TempMap[blockNumber.String()]; !ok {
   152  		log.Warn("Warn Call getPposCacheFromTemp of PPOS_TEMP, the PPOS storage cache is empty by blockNumber !!!!! Direct short-circuit", "blockNumber", blockNumber.Uint64(), "blockHash", blockHash.Hex())
   153  		temp.lock.Unlock()
   154  		return ppos_storage
   155  	}else {
   156  
   157  		if pposStorage, ok := hashTemp[blockHash]; !ok {
   158  			log.Warn("Warn Call getPposCacheFromTemp of PPOS_TEMP, the PPOS storage cache is empty by blockHash !!!!! Direct short-circuit", "blockNumber", blockNumber.Uint64(), "blockHash", blockHash.Hex())
   159  			temp.lock.Unlock()
   160  			return ppos_storage
   161  		}else {
   162  			start := common.NewTimer()
   163  			start.Begin()
   164  			storage = pposStorage.Copy()
   165  			log.Debug("Call getPposCacheFromTemp of PPOS_TEMP, Copy ppos_storage FINISH !!!!!!", "blockNumber", blockNumber.Uint64(), "blockHash", blockHash.Hex(), "Time spent", fmt.Sprintf("%v ms", start.End()))
   166  		}
   167  	}
   168  	temp.lock.Unlock()
   169  	return storage
   170  }
   171  
   172  // Set ppos storage cache by same block
   173  func (temp *PPOS_TEMP) SubmitPposCache2Temp(blockNumber, blockInterval *big.Int, blockHash common.Hash, storage *Ppos_storage)  {
   174  	log.Info("Call SubmitPposCache2Temp of PPOS_TEMP", "blockNumber", blockNumber.String(), "blockHash", blockHash.Hex(),
   175  		"blockInterval", blockInterval, "Before SubmitPposCache2Temp, THEN PPOS_TEMP len ", len(temp.TempMap), "Block Count", temp.BlockCount)
   176  
   177  	start := common.NewTimer()
   178  	start.Begin()
   179  
   180  	empty := verifyStorageEmpty(storage)
   181  
   182  
   183  	temp.lock.Lock()
   184  	/**
   185  	first condition blockNumber
   186  	There are four kinds.
   187  	1a、origin data is empty by blockNumber AND input data is not empty; 	then we will Add (set) input data into global temp
   188  	2a、origin data is empty by blockNumber AND input data is empty;     	then we direct short-circuit
   189  	3a、origin data is not empty by blockNumber AND input data is not empty; then we will update (set) global temp by indata
   190  	4a、origin data is not empty by blockNumber AND input data is empty; 	then we will delete global temp data
   191  	 */
   192  
   193  	originHashTemp, hasNum := temp.TempMap[blockNumber.String()]
   194  	// match 1a
   195  	if !hasNum && !empty {
   196  		originHashTemp = make(hashTempMap, 1)
   197  		originHashTemp[blockHash] = storage
   198  		temp.TempMap[blockNumber.String()] = originHashTemp
   199  
   200  		temp.BlockCount += 1
   201  
   202  		temp.deleteAnyTemp(blockNumber, blockInterval, blockHash)
   203  		temp.lock.Unlock()
   204  		return
   205  	}else if  !hasNum && empty { // match 2a
   206  		log.Debug("Call SubmitPposCache2Temp of PPOS_TEMP, origin ppos_storage and input ppos_storage is empty by BlockNumber !!!! Direct short-circuit", "blockNumber", blockNumber.Uint64(),
   207  			"blockHash", blockHash.Hex(), "blockInterval", blockInterval, " Before SubmitPposCache2Temp, THEN PPOS_TEMP len ", len(temp.TempMap), "Block Count", temp.BlockCount, "Time spent", fmt.Sprintf("%v ms", start.End()))
   208  		temp.lock.Unlock()
   209  		return
   210  	}
   211  
   212  	_, hasHash := originHashTemp[blockHash]
   213  
   214  	/**
   215  	second condition blockHash
   216  	There are four kinds, too.
   217  	1b、origin data is empty by blockHash AND input data is not empty; 		then we will Add (set) indata into global temp
   218  	2b、origin data is empty by blockHash AND input data is empty;     		then we direct short-circuit
   219  	3b、origin data is not empty by blockHash AND input data is not empty; 	then we will update (set) global temp by indata
   220  	4b、origin data is not empty by blockHash AND input data is empty; 		then we will delete global temp data
   221  	 */
   222  
   223  	 // match 1b
   224  	 if !hasHash && !empty {
   225  		 originHashTemp[blockHash] = storage
   226  		 temp.TempMap[blockNumber.String()] = originHashTemp
   227  
   228  		 temp.BlockCount += 1
   229  
   230  		 temp.deleteAnyTemp(blockNumber, blockInterval, blockHash)
   231  		 temp.lock.Unlock()
   232  		 return
   233  	 }else if  !hasHash && empty { // match 2b
   234  		 log.Debug("Call SubmitPposCache2Temp of PPOS_TEMP, origin ppos_storage and input ppos_storage is empty by BlockHash !!!! Direct short-circuit", "blockNumber", blockNumber.Uint64(),
   235  			 "blockHash", blockHash.Hex(), "blockInterval", blockInterval, " Before SubmitPposCache2Temp, THEN PPOS_TEMP len ", len(temp.TempMap), "Block Count", temp.BlockCount, "Time spent", fmt.Sprintf("%v ms", start.End()))
   236  		 temp.lock.Unlock()
   237  		 return
   238  	 }
   239  
   240  	 // now remain 3a 4a 3b 4b
   241  	 if hasHash && empty { // delete origin data
   242  		delete(originHashTemp, blockHash)
   243  		temp.BlockCount -= 1
   244  		if len(originHashTemp) == 0 {
   245  			delete(temp.TempMap, blockNumber.String())
   246  		}
   247  
   248  		temp.deleteAnyTemp(blockNumber, blockInterval, blockHash)
   249  	 }else if hasHash && !empty {
   250  		 originHashTemp[blockHash] = storage
   251  		 temp.TempMap[blockNumber.String()] = originHashTemp
   252  
   253  		 temp.deleteAnyTemp(blockNumber, blockInterval, blockHash)
   254  	 }
   255  	temp.lock.Unlock()
   256  	log.Debug("Call SubmitPposCache2Temp of PPOS_TEMP,SUCCESS !!!!!!", "blockNumber", blockNumber.Uint64(), "blockHash", blockHash.Hex(),
   257  		"blockInterval", blockInterval, " Before SubmitPposCache2Temp, THEN PPOS_TEMP len ", len(temp.TempMap), "Block Count", temp.BlockCount, "Time spent", fmt.Sprintf("%v ms", start.End()))
   258  
   259  }
   260  
   261  func (temp *PPOS_TEMP) Commit2DB(blockNumber *big.Int, blockHash common.Hash) error {
   262  	start := common.NewTimer()
   263  	start.Begin()
   264  
   265  
   266  	var ps *Ppos_storage
   267  	temp.lock.Lock()
   268  	if hashMap, ok := temp.TempMap[blockNumber.String()]; !ok {
   269  		temp.lock.Unlock()
   270  		return nil
   271  	}else {
   272  		if ppos_storage, ok := hashMap[blockHash]; !ok {
   273  			temp.lock.Unlock()
   274  			return nil
   275  		}else {
   276  			ps = ppos_storage
   277  		}
   278  	}
   279  	temp.lock.Unlock()
   280  
   281  
   282  
   283  
   284  	if pposTemp := buildPBStorage(blockNumber, blockHash, ps); nil == pposTemp {
   285  		log.Debug("Call Commit2DB FINISH !!!! , PPOS storage is Empty, do not write disk AND direct short-circuit ...")
   286  		return nil
   287  	}else{
   288  		// write ppos_storage into disk with protobuf
   289  		if data, err := proto.Marshal(pposTemp); nil != err {
   290  			log.Error("Failed to Commit2DB", "proto err", err, "Time spent", fmt.Sprintf("%v ms", start.End()))
   291  			return err
   292  		}else {
   293  			if len(data) != 0 {
   294  
   295  				// TODO
   296  
   297  				if err := temp.db.Put(PPOS_STORAGE_KEY, data); err != nil {
   298  					log.Error("Failed to Call Commit2DB:" + WRITE_PPOS_ERR.Error(), "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "data len", len(data), "Time spent", fmt.Sprintf("%v ms", start.End()), "err", err)
   299  					return WRITE_PPOS_ERR
   300  				}
   301  
   302  				temp.BlockNumber = blockNumber
   303  				temp.BlockHash = blockHash
   304  
   305  			}
   306  			log.Info("Call Commit2DB, write ppos storage data to disk", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "data len", len(data), "dataMD5", md5.Sum(data), "Time spent", fmt.Sprintf("%v ms", start.End()))
   307  		}
   308  	}
   309  	return nil
   310  }
   311  
   312  // Gets ppos_storag pb from db
   313  func  (temp *PPOS_TEMP) GetPPosStorageProto() (common.Hash, []byte, error) {
   314  	start := common.NewTimer()
   315  	start.Begin()
   316  	if data, err := temp.db.Get(PPOS_STORAGE_KEY); nil != err {
   317  		if ppos_empty_indb == err.Error() {
   318  			log.Debug("Call GetPPosStorageProto, ppos storage is empty in disk ...")
   319  			return common.Hash{}, nil, nil
   320  		}else {
   321  			log.Warn("Failed to Call GetPPosStorageProto to get Global ppos temp by levelDB", "err", err)
   322  			return common.Hash{}, nil, err
   323  		}
   324  	} else {
   325  		log.Debug("Call GetPPosStorageProto to Unmarshal Global ppos temp", "pb data len", len(data))
   326  
   327  		pb_pposTemp := new(PB_PPosTemp)
   328  		if err := proto.Unmarshal(data, pb_pposTemp); err != nil {
   329  			log.Error("Failed to Call GetPPosStorageProto to Unmarshal Global ppos temp", "err", err)
   330  			return common.Hash{}, nil, err
   331  		}else {
   332  			// TODO
   333  
   334  			//PrintObject("GetPPosStorageProto resolve the data of PB:", pb_pposTemp)
   335  			curr_Num, _ := new(big.Int).SetString(pb_pposTemp.BlockNumber, 10)
   336  			if curr_Num.Cmp(big.NewInt(common.BaseElection - 1)) < 0 {
   337  				return common.Hash{}, nil, nil
   338  			}
   339  
   340  			log.Debug("Call GetPPosStorageProto FINISH !!!!", "blockNumber", pb_pposTemp.BlockNumber, "blockHash", pb_pposTemp.BlockHash, "data len", len(data), "dataMD5", md5.Sum(data), "Time spent", fmt.Sprintf("%v ms", start.End()))
   341  			return common.HexToHash(pb_pposTemp.BlockHash), data, nil
   342  		}
   343  	}
   344  }
   345  
   346  // Flush data into db
   347  func (temp *PPOS_TEMP) PushPPosStorageProto(data []byte)  error {
   348  	if len(data) == 0 {
   349  		return nil
   350  	}
   351  	start := common.NewTimer()
   352  	start.Begin()
   353  	pb_pposTemp := new(PB_PPosTemp)
   354  	if err := proto.Unmarshal(data, pb_pposTemp); err != nil {
   355  		log.Error("Failed to Call PushPPosStorageProto to Unmarshal Global ppos temp", "err", err)
   356  		return err
   357  	}else {
   358  		/**
   359  		build global ppos_temp
   360  		 */
   361  		 // TODO
   362  
   363  		log.Debug("PushPPosStorageProto input params:", "data len", len(data), "dataMD5", md5.Sum(data))
   364  
   365  		//PrintObject("PushPPosStorageProto resolve the data of PB, will flush disk:", pb_pposTemp)
   366  
   367  		var hashMap map[common.Hash]*Ppos_storage
   368  
   369  		ppos_temp.lock.Lock()
   370  
   371  		if hashData, ok := ppos_temp.TempMap[pb_pposTemp.BlockNumber]; ok {
   372  			hashMap = hashData
   373  		}else {
   374  			hashMap = make(map[common.Hash]*Ppos_storage, 1)
   375  		}
   376  
   377  		pposStorage := unmarshalPBStorage(pb_pposTemp)
   378  
   379  
   380  
   381  		blockHash := common.HexToHash(pb_pposTemp.BlockHash)
   382  		hashMap[blockHash] = pposStorage
   383  		ppos_temp.TempMap[pb_pposTemp.BlockNumber] = hashMap
   384  
   385  
   386  
   387  		ppos_temp.lock.Unlock()
   388  
   389  
   390  		// flush data into disk
   391  		if len(data) != 0 {
   392  			log.Debug("Call PushPPosStorageProto flush data into disk start ...", "blockNumber", pb_pposTemp.BlockNumber, "blockHash", pb_pposTemp.BlockHash, "data len", len(data))
   393  			if err := temp.db.Put(PPOS_STORAGE_KEY, data); err != nil {
   394  				log.Error("Failed to Call PushPPosStorageProto:" + WRITE_PPOS_ERR.Error(), "blockNumber", pb_pposTemp.BlockNumber, "blockHash", pb_pposTemp.BlockHash, "data len", len(data), "Time spent", fmt.Sprintf("%v ms", start.End()), "err", err)
   395  				return WRITE_PPOS_ERR
   396  			}
   397  		}
   398  
   399  		num, _ := new(big.Int).SetString(pb_pposTemp.BlockNumber, 10)
   400  
   401  		temp.BlockNumber = num
   402  		temp.BlockHash = blockHash
   403  	}
   404  
   405  
   406  
   407  	log.Debug("Call PushPPosStorageProto FINISH !!!!", "blockNumber", pb_pposTemp.BlockNumber, "blockHash", pb_pposTemp.BlockHash, "data len", len(data), "Time spent", fmt.Sprintf("%v ms", start.End()))
   408  	return nil
   409  }
   410  
   411  
   412  func buildPBStorage(blockNumber *big.Int, blockHash common.Hash, ps *Ppos_storage) *PB_PPosTemp {
   413  	ppos_temp := new(PB_PPosTemp)
   414  	ppos_temp.BlockNumber = blockNumber.String()
   415  	ppos_temp.BlockHash = blockHash.Hex()
   416  
   417  	var empty int = 0  // 0: empty 1: no
   418  	var wg sync.WaitGroup
   419  
   420  	/**
   421  	candidate related
   422  	*/
   423  	if nil != ps.c_storage {
   424  
   425  		canTemp := new(CandidateTemp)
   426  
   427  
   428  		wg.Add(6)
   429  		// previous witness
   430  		go func() {
   431  			if queue := buildPBcanqueue("buildPBStorage pres", ps.c_storage.pres); len(queue) != 0 {
   432  				canTemp.Pres = queue
   433  				empty |= 1
   434  			}
   435  			wg.Done()
   436  		}()
   437  		// current witness
   438  		go func() {
   439  			if queue := buildPBcanqueue("buildPBStorage currs", ps.c_storage.currs); len(queue) != 0 {
   440  				canTemp.Currs = queue
   441  				empty |= 1
   442  			}
   443  			wg.Done()
   444  		}()
   445  		// next witness
   446  		go func() {
   447  			if queue := buildPBcanqueue("buildPBStorage nexts", ps.c_storage.nexts); len(queue) != 0 {
   448  				canTemp.Nexts = queue
   449  				empty |= 1
   450  			}
   451  			wg.Done()
   452  		}()
   453  		// immediate
   454  		go func() {
   455  			if queue := buildPBcanqueue("buildPBStorage imms", ps.c_storage.imms); len(queue) != 0 {
   456  				canTemp.Imms = queue
   457  				empty |= 1
   458  			}
   459  			wg.Done()
   460  		}()
   461  		// reserve
   462  		go func() {
   463  			if queue := buildPBcanqueue("buildPBStorage res", ps.c_storage.res); len(queue) != 0 {
   464  				canTemp.Res = queue
   465  				empty |= 1
   466  			}
   467  			wg.Done()
   468  		}()
   469  
   470  		// refund
   471  		go func() {
   472  			if refundMap := buildPBrefunds(ps.c_storage.refunds); len(refundMap) != 0 {
   473  				canTemp.Refunds = refundMap
   474  				empty |= 1
   475  			}
   476  			wg.Done()
   477  		}()
   478  
   479  		wg.Wait()
   480  		ppos_temp.CanTmp = canTemp
   481  	}
   482  
   483  	/**
   484  	ticket related
   485  	*/
   486  	if nil != ps.t_storage {
   487  		tickTemp := new(TicketTemp)
   488  
   489  		tickTemp.Sq = ps.t_storage.Sq
   490  
   491  		// SQ
   492  		if ps.t_storage.Sq != -1 {
   493  			empty |= 1
   494  		}
   495  
   496  		//wg.Add(3)
   497  
   498  		// ticketInfos
   499  		/*go func() {
   500  			if ticketMap := buildPBticketMap(ps.t_storage.Infos); len(ticketMap) != 0 {
   501  				tickTemp.Infos = ticketMap
   502  				empty |= 1
   503  			}
   504  			wg.Done()
   505  		}()*/
   506  
   507  		//// ExpireTicket
   508  		//go func() {
   509  		//	if ets := buildPBexpireTicket(ps.t_storage.Ets); len(ets) != 0 {
   510  		//		tickTemp.Ets = ets
   511  		//		empty |= 1
   512  		//	}
   513  		//	wg.Done()
   514  		//}()
   515  
   516  		// ticket's attachment  of node
   517  		//go func() {
   518  			if dependency := buildPBdependencys(ps.t_storage.Dependencys); len(dependency) != 0 {
   519  				tickTemp.Dependencys = dependency
   520  				empty |= 1
   521  			}
   522  			//wg.Done()
   523  		//}()
   524  
   525  		//wg.Wait()
   526  		ppos_temp.TickTmp = tickTemp
   527  	}
   528  
   529  	if empty == 0 {
   530  		return nil
   531  	}
   532  	return ppos_temp
   533  }
   534  
   535  
   536  func unmarshalPBStorage(pb_temp *PB_PPosTemp) *Ppos_storage {
   537  
   538  	ppos_storage := new(Ppos_storage)
   539  
   540  	/**
   541  	candidate related
   542  	*/
   543  	canGlobalTemp := pb_temp.CanTmp
   544  	if nil !=  canGlobalTemp {
   545  
   546  		canTemp := new(candidate_temp)
   547  
   548  		buildQueueFunc := func(arr []*CandidateInfo) types.CandidateQueue {
   549  			if len(arr) == 0 {
   550  				return nil
   551  			}
   552  			queue := make(types.CandidateQueue, len(arr))
   553  			for i, can := range arr {
   554  				deposit, _ := new(big.Int).SetString(can.Deposit, 10)
   555  				num, _ := new(big.Int).SetString(can.BlockNumber, 10)
   556  				canInfo := &types.Candidate{
   557  					Deposit: 		deposit,
   558  					BlockNumber:	num,
   559  					TxIndex:		can.TxIndex,
   560  					CandidateId:	discover.MustHexID(can.CandidateId),
   561  					Host:        	can.Host,
   562  					Port:         	can.Port,
   563  					Owner:  		common.HexToAddress(can.Owner),
   564  					Extra:  		can.Extra,
   565  					Fee:  			can.Fee,
   566  					TxHash: 		common.HexToHash(can.TxHash),
   567  					TOwner: 		common.HexToAddress(can.TOwner),
   568  				}
   569  				queue[i] = canInfo
   570  			}
   571  			return queue
   572  		}
   573  
   574  		// previous witness
   575  		canTemp.pres = buildQueueFunc(canGlobalTemp.Pres)
   576  		// current witness
   577  		canTemp.currs = buildQueueFunc(canGlobalTemp.Currs)
   578  		// next witness
   579  		canTemp.nexts = buildQueueFunc(canGlobalTemp.Nexts)
   580  		// immediate
   581  		canTemp.imms = buildQueueFunc(canGlobalTemp.Imms)
   582  		// reserve
   583  		canTemp.res = buildQueueFunc(canGlobalTemp.Res)
   584  		// refund
   585  		/*if len(canGlobalTemp.Refunds) != 0 {
   586  
   587  
   588  		}*/
   589  
   590  
   591  
   592  		defeatMap := make(refundStorage, len(canGlobalTemp.Refunds))
   593  
   594  		for nodeId, refundArr := range canGlobalTemp.Refunds {
   595  
   596  			if len(refundArr.Defeats) == 0 {
   597  				continue
   598  			}
   599  
   600  			defeatArr := make(types.RefundQueue, len(refundArr.Defeats))
   601  			for i, defeat := range refundArr.Defeats {
   602  
   603  				deposit, _ := new(big.Int).SetString(defeat.Deposit, 10)
   604  				num, _ := new(big.Int).SetString(defeat.BlockNumber, 10)
   605  
   606  				refund := &types.CandidateRefund{
   607  					Deposit:  		deposit,
   608  					BlockNumber: 	num,
   609  					Owner: 			common.HexToAddress(defeat.Owner),
   610  				}
   611  				defeatArr[i] = refund
   612  			}
   613  			defeatMap[discover.MustHexID(nodeId)] = defeatArr
   614  		}
   615  
   616  		canTemp.refunds = defeatMap
   617  		ppos_storage.c_storage = canTemp
   618  	}
   619  
   620  
   621  	/**
   622  	ticket related
   623  	 */
   624  	tickGlobalTemp := pb_temp.TickTmp
   625  	if nil != tickGlobalTemp {
   626  
   627  		tickTemp := new(ticket_temp)
   628  
   629  		// SQ
   630  		tickTemp.Sq = tickGlobalTemp.Sq
   631  
   632  		// ticketInfo map
   633  		/*if len(tickGlobalTemp.Infos) != 0 {
   634  
   635  			infoMap := make(map[common.Hash]*types.Ticket, len(tickGlobalTemp.Infos))
   636  			for tid, tinfo := range tickGlobalTemp.Infos {
   637  				deposit, _ := new(big.Int).SetString(tinfo.Deposit, 10)
   638  				num, _ := new(big.Int).SetString(tinfo.BlockNumber, 10)
   639  				ticketInfo := &types.Ticket{
   640  					Owner: 			common.BytesToAddress(tinfo.Owner),
   641  					Deposit:		deposit,
   642  					CandidateId: 	discover.MustBytesID(tinfo.CandidateId),
   643  					BlockNumber: 	num,
   644  					Remaining:		tinfo.Remaining,
   645  				}
   646  
   647  				infoMap[common.HexToHash(tid)] = ticketInfo
   648  			}
   649  			tickTemp.Infos = infoMap
   650  		}*/
   651  
   652  
   653  		//// ExpireTicket map
   654  		//if len(tickGlobalTemp.Ets) != 0 {
   655  		//	ets := make(map[string][]common.Hash, len(tickGlobalTemp.Ets))
   656  		//
   657  		//	for blockNum, ticketIdArr := range tickGlobalTemp.Ets {
   658  		//
   659  		//		if len(ticketIdArr.TxHashs) == 0 {
   660  		//			continue
   661  		//		}
   662  		//
   663  		//		ticketIds := make([]common.Hash, len(ticketIdArr.TxHashs))
   664  		//		for i, ticketId := range ticketIdArr.TxHashs {
   665  		//			ticketIds[i] = common.BytesToHash(ticketId)
   666  		//		}
   667  		//		ets[blockNum] = ticketIds
   668  		//	}
   669  		//
   670  		//	tickTemp.Ets = ets
   671  		//}
   672  
   673  		// ticket's attachment  of node
   674  		/*if len(tickGlobalTemp.Dependencys) != 0 {
   675  
   676  
   677  		}*/
   678  
   679  
   680  
   681  		dependencyMap := make(map[discover.NodeID]*ticketDependency, len(tickGlobalTemp.Dependencys))
   682  
   683  		for nodeIdStr, pb_dependency := range tickGlobalTemp.Dependencys {
   684  
   685  			dependencyInfo := new(ticketDependency)
   686  			//dependencyInfo.Age = pb_dependency.Age
   687  			dependencyInfo.Num = pb_dependency.Num
   688  
   689  
   690  			/*tidArr := make([]common.Hash, len(pb_dependency.Tids))
   691  
   692  			for i, ticketId := range pb_dependency.Tids {
   693  				tidArr[i] = common.BytesToHash(ticketId)
   694  			}
   695  
   696  			dependencyInfo.Tids = tidArr*/
   697  
   698  
   699  
   700  			fieldArr := make([]*ticketInfo, len(pb_dependency.Tinfo))
   701  			for j, field := range pb_dependency.Tinfo {
   702  
   703  				price, _ := new(big.Int).SetString(field.Price, 10)
   704  				f := &ticketInfo{
   705  					TxHash: 	common.HexToHash(field.TxHash),
   706  					Remaining: 	field.Remaining,
   707  					Price: 		price,
   708  				}
   709  
   710  				fieldArr[j] =  f
   711  			}
   712  			dependencyInfo.Tinfo = fieldArr
   713  
   714  			dependencyMap[discover.MustHexID(nodeIdStr)] = dependencyInfo
   715  		}
   716  
   717  		tickTemp.Dependencys = dependencyMap
   718  		ppos_storage.t_storage = tickTemp
   719  	}
   720  
   721  	return ppos_storage
   722  }
   723  
   724  func buildPBcanqueue (title string, canQqueue types.CandidateQueue) []*CandidateInfo {
   725  
   726  	PrintObject(title + " ,buildPBcanqueue:", canQqueue)
   727  
   728  	pbQueue := make([]*CandidateInfo, len(canQqueue))
   729  	if len(canQqueue) == 0 {
   730  		return pbQueue
   731  	}
   732  
   733  	for i, can := range canQqueue {
   734  		canInfo := &CandidateInfo{
   735  			Deposit: 		can.Deposit.String(),
   736  			BlockNumber:	can.BlockNumber.String(),
   737  			TxIndex:		can.TxIndex,
   738  			CandidateId:	can.CandidateId.String(),
   739  			Host:			can.Host,
   740  			Port:			can.Port,
   741  			Owner:			can.Owner.String(),
   742  			Extra:			can.Extra,
   743  			Fee: 			can.Fee,
   744  			TxHash: 		can.TxHash.String(),
   745  			TOwner: 		can.TOwner.String(),
   746  		}
   747  		pbQueue[i] = canInfo
   748  	}
   749  	return pbQueue
   750  }
   751  
   752  
   753  func buildPBrefunds(refunds refundStorage) map[string]*RefundArr {
   754  
   755  	PrintObject("buildPBrefunds", refunds)
   756  
   757  	if len(refunds) == 0 {
   758  		return nil
   759  	}
   760  
   761  	refundMap := make(map[string]*RefundArr, len(refunds))
   762  
   763  	for nodeId, rs := range refunds {
   764  
   765  		if len(rs) == 0 {
   766  			continue
   767  		}
   768  		defeats := make([]*Refund, len(rs))
   769  		for i, refund := range rs {
   770  			refundInfo := &Refund{
   771  				Deposit:     	refund.Deposit.String(),
   772  				BlockNumber:	refund.BlockNumber.String(),
   773  				Owner:			refund.Owner.String(),
   774  			}
   775  			defeats[i] = refundInfo
   776  		}
   777  
   778  		refundArr := &RefundArr{
   779  			Defeats: defeats,
   780  		}
   781  		refundMap[nodeId.String()] = refundArr
   782  	}
   783  	return refundMap
   784  }
   785  
   786  
   787  //func buildPBticketMap(tickets map[common.Hash]*types.Ticket) map[string]*TicketInfo {
   788  //	if len(tickets) == 0 {
   789  //		return nil
   790  //	}
   791  //
   792  //	pb_ticketMap := make(map[string]*TicketInfo, len(tickets))
   793  //
   794  //	for tid, tinfo := range tickets {
   795  //		ticketInfo := &TicketInfo{
   796  //			Owner:       tinfo.Owner.Bytes(),
   797  //			Deposit:     tinfo.Deposit.String(),
   798  //			CandidateId: tinfo.CandidateId.Bytes(),
   799  //			BlockNumber: tinfo.BlockNumber.String(),
   800  //			Remaining:   tinfo.Remaining,
   801  //		}
   802  //		pb_ticketMap[tid.String()] = ticketInfo
   803  //	}
   804  //	return pb_ticketMap
   805  //}
   806  
   807  
   808  //func buildPBexpireTicket(ets map[string][]common.Hash) map[string]*TxHashArr  {
   809  //	if len(ets) == 0 {
   810  //		return nil
   811  //	}
   812  //
   813  //	pb_ets := make(map[string]*TxHashArr, len(ets))
   814  //
   815  //	for blockNumber, ticketIdArr := range ets {
   816  //
   817  //		if len(ticketIdArr) == 0 {
   818  //			continue
   819  //		}
   820  //
   821  //		txHashs := make([][]byte, len(ticketIdArr))
   822  //
   823  //		for i, tid := range ticketIdArr {
   824  //			txHashs[i] = tid.Bytes()
   825  //		}
   826  //
   827  //		txHashArr := new(TxHashArr)
   828  //		txHashArr.TxHashs = txHashs
   829  //		pb_ets[blockNumber] = txHashArr
   830  //	}
   831  //	return pb_ets
   832  //}
   833  
   834  
   835  func buildPBdependencys(dependencys map[discover.NodeID]*ticketDependency) map[string]*TicketDependency {
   836  	if len(dependencys) == 0 {
   837  		return nil
   838  	}
   839  
   840  	pb_dependency := make(map[string]*TicketDependency, len(dependencys))
   841  
   842  	for nodeId, dependency := range dependencys {
   843  
   844  		/*tidArr := make([][]byte, len(dependency.Tids))
   845  
   846  		for i, ticketId := range dependency.Tids {
   847  			tidArr[i] = ticketId.Bytes()
   848  		}*/
   849  
   850  
   851  		if dependency.Num == 0 && len(dependency.Tinfo) == 0 {
   852  			continue
   853  		}
   854  
   855  		fieldArr := make([]*Field, len(dependency.Tinfo))
   856  
   857  
   858  		for i, field := range dependency.Tinfo {
   859  
   860  			f := &Field{
   861  				TxHash:		field.TxHash.String(),
   862  				Remaining: 	field.Remaining,
   863  				Price: 		field.Price.String(),
   864  			}
   865  			fieldArr[i] = f
   866  		}
   867  
   868  		depenInfo := &TicketDependency{
   869  			//Age:  dependency.Age,
   870  			Num:  dependency.Num,
   871  			//Tids: tidArr,
   872  			Tinfo: 	fieldArr,
   873  		}
   874  
   875  		pb_dependency[nodeId.String()] = depenInfo
   876  	}
   877  	return pb_dependency
   878  }
   879  
   880  func (temp *PPOS_TEMP) deleteAnyTemp (blockNumber, blockInterval *big.Int, blockHash common.Hash) {
   881  
   882  	// delete font any data
   883  	if big.NewInt(0).Cmp(blockInterval) > 0 {
   884  		log.Error("WARN WARN WARN !!! Call SubmitPposCache2Temp of PPOS_TEMP FINISH !!!!!! blockInterval is NEGATIVE NUMBER", "blockNumber", blockNumber.String(),
   885  			"blockHash", blockHash.Hex(), "blockInterval", blockInterval, "After SubmitPposCache2Temp, THEN PPOS_TEMP len ", len(temp.TempMap), "Block Count", temp.BlockCount)
   886  		return
   887  	}
   888  
   889  	// blockInterval is the difference of block height between
   890  	// the highest block in memory and the highest block in the chain
   891  	interval := new(big.Int).Add(blockInterval, big.NewInt(30))
   892  
   893  	// del old cache
   894  	// blocknumber: current memory block
   895  	target := new(big.Int).Sub(blockNumber, interval)
   896  	for number := range temp.TempMap {
   897  		if currentNum, ok := new(big.Int).SetString(number, 0); ok {
   898  			if currentNum.Cmp(target) < 0 {
   899  
   900  				hashMap, ok := temp.TempMap[currentNum.String()]
   901  
   902  				// delete current number related ppos data
   903  				delete(temp.TempMap, number)
   904  				// decr block count
   905  				if ok {
   906  					temp.BlockCount -= uint32(len(hashMap))
   907  				}
   908  			}
   909  		}
   910  	}
   911  	log.Debug("Call SubmitPposCache2Temp of PPOS_TEMP FINISH !!!!!!", "blockNumber", blockNumber.String(), "blockHash", blockHash.Hex(),
   912  		"blockInterval", blockInterval, "After SubmitPposCache2Temp, THEN PPOS_TEMP len ", len(temp.TempMap), "Block Count", temp.BlockCount)
   913  
   914  }
   915  
   916  func verifyStorageEmpty(storage *Ppos_storage) bool {
   917  	if nil == storage.c_storage && nil == storage.t_storage {
   918  		return true
   919  	}
   920  
   921  	var canEmpty, tickEmpty bool
   922  
   923  	canStorage := storage.c_storage
   924  	if nil != canStorage {
   925  		if len(canStorage.pres) == 0 && len(canStorage.currs) == 0 && len(canStorage.nexts) == 0 &&
   926  			len(canStorage.imms) == 0 && len(canStorage.res) == 0 && len(canStorage.refunds) == 0 {
   927  			canEmpty = true
   928  		}
   929  	}
   930  
   931  	tickStorage := storage.t_storage
   932  	if nil != tickStorage {
   933  		if tickStorage.Sq == -1 && /*len(tickStorage.Infos) == 0 &&
   934  			len(tickStorage.Ets) == 0 &&*/ len(tickStorage.Dependencys) == 0 {
   935  			tickEmpty = true
   936  		}
   937  	}
   938  	if canEmpty && tickEmpty {
   939  		return true
   940  	}
   941  	return false
   942  }
   943  
   944  
   945  
   946  func PrintObject(s string, obj interface{}) {
   947  	objs, _ := json.Marshal(obj)
   948  	log.Debug(s, "==", string(objs))
   949  }