func (pe *PreElecting) ToPack() *PreElecting {
	if pe == nil {
		return nil
	}
	return &PreElecting{
		ChainID:   pe.ChainID,
		Phase:     pe.Phase,
		Seed:      pe.Seed.Clone(),
		Count:     pe.Count,
		Start:     pe.Start,
		Expire:    pe.Expire,
		NidHashes: common.CopyHashs(pe.NidHashes),
	}
}
Generate objects for packaging, the pre-election information in the block does not include BlockHash
package models
import (
	"bytes"
	"errors"
	"fmt"
	"sort"
	"github.com/ThinkiumGroup/go-common"
	"github.com/ThinkiumGroup/go-thinkium/consts"
)
type (
	PreelectionStart struct {
		ChainID      common.ChainID  
		ParentHeight common.Height   
	}
	PreelectionConnect struct {
		ChainID common.ChainID  
		Height  common.Height   
		Comm    *Committee      
	}
	PreelectionSync struct {
		ChainID common.ChainID
		Height  common.Height
	}
	PreelectionExamine struct {
		ChainID common.ChainID
		Height  common.Height
	}
	PreelectionExit struct {
		ChainID common.ChainID
		Height  common.Height
	}
)
func (p *PreelectionStart) GetChainID() common.ChainID {
	return common.MainChainID
}
func (p *PreelectionStart) String() string {
	if p == nil {
		return "PEStart<nil>"
	}
	return fmt.Sprintf("PEStart{ChainID:%d ParentHeight:%d}", p.ChainID, p.ParentHeight)
}
func (p *PreelectionConnect) GetChainID() common.ChainID {
	return common.MainChainID
}
func (p *PreelectionConnect) String() string {
	if p == nil {
		return "PEConnect<nil>"
	}
	return fmt.Sprintf("PEConnect{ChainID:%d Height:%d Comm:%s}", p.ChainID, p.Height, p.Comm)
}
func (p PreelectionSync) GetChainID() common.ChainID {
	return p.ChainID
}
func (p *PreelectionSync) String() string {
	if p == nil {
		return "PESync<nil>"
	}
	return fmt.Sprintf("PESync{ChainID:%d Height:%d}", p.ChainID, p.Height)
}
func (p PreelectionExamine) GetChainID() common.ChainID {
	return p.ChainID
}
func (p *PreelectionExamine) String() string {
	if p == nil {
		return "PEExamine<nil>"
	}
	return fmt.Sprintf("PEExamine{ChainID:%d Height:%d}", p.ChainID, p.Height)
}
func (p PreelectionExit) GetChainID() common.ChainID {
	return p.ChainID
}
func (p *PreelectionExit) String() string {
	if p == nil {
		return "PEExit<nil>"
	}
	return fmt.Sprintf("PEExit{ChainID:%d Height:%d}", p.ChainID, p.Height)
}
type PreElectPhase byte
const (
	PECreating PreElectPhase = 0x0 + iota  
	PEElecting                             
	PEStarting                             
	PEExiting                              
)
func (p PreElectPhase) String() string {
	switch p {
	case PECreating:
		return "Creating"
	case PEElecting:
		return "Electing"
	case PEStarting:
		return "Starting"
	case PEExiting:
		return "Exiting"
	default:
		return fmt.Sprintf("unknown-0x%x", byte(p))
	}
}
type PreElecting struct {
	ChainID common.ChainID
	Phase PreElectPhase
	Seed *common.Seed
	Count int
	Start common.Height
	CachedHash *common.Hash
	NidHashes []common.Hash
	Expire common.Height
}
func (pe *PreElecting) String() string {
	if pe == nil {
		return "Preelect<nil>"
	}
	return fmt.Sprintf("Preelect{ChainID:%d %s Seed:%x Count:%d Start:%d StartHash:%x NidHashes:%d Expire:%d}",
		pe.ChainID, pe.Phase, common.ForPrint(pe.Seed), pe.Count,
		pe.Start, common.ForPrint(pe.CachedHash), len(pe.NidHashes), pe.Expire)
}
func (pe *PreElecting) IsValidManagedComm() bool {
	if pe == nil {
		return false
	}
	return len(pe.NidHashes) >= consts.MinimumCommSize
}
func (pe *PreElecting) IsVrf() bool {
	return pe != nil && pe.Seed != nil && len(pe.NidHashes) == 0
}
func (pe *PreElecting) IsManagedComm() bool {
	return pe != nil && pe.Seed == nil && len(pe.NidHashes) > 0
}
func PreelectSeed(seed common.Seed, blockHash common.Hash) common.Seed {
	h := common.Hash256(seed[:], blockHash[:])
	return common.BytesToSeed(h[:])
}
func (pe *PreElecting) PreSeed() (*common.Seed, error) {
	if pe.Seed == nil || pe.CachedHash == nil {
		return nil, fmt.Errorf("vrf preelect seed (%x) or hash (%x) is nil",
			common.ForPrint(pe.Seed),
			common.ForPrint(pe.CachedHash))
	}
	preseed := PreelectSeed(*pe.Seed, *pe.CachedHash)
	return &preseed, nil
}
func (pe *PreElecting) Clone() *PreElecting {
	if pe == nil {
		return nil
	}
	return &PreElecting{
		ChainID:    pe.ChainID,
		Phase:      pe.Phase,
		Seed:       pe.Seed.Clone(),
		Count:      pe.Count,
		Start:      pe.Start,
		CachedHash: pe.CachedHash.Clone(),
		NidHashes:  common.CopyHashs(pe.NidHashes),
		Expire:     pe.Expire,
	}
}