18 "github.com/vapor/chain"
19 "github.com/vapor/common"
20 "github.com/vapor/config"
21 "github.com/vapor/consensus"
22 engine "github.com/vapor/consensus/consensus"
23 "github.com/vapor/crypto"
24 "github.com/vapor/protocol/bc"
25 "github.com/vapor/protocol/bc/types"
26 "github.com/vapor/protocol/vm"
29 type Delegate struct {
30 DelegateAddress string `json:"delegate_address"`
31 Votes uint64 `json:"votes"`
34 type DelegateWrapper struct {
36 by func(p, q *Delegate) bool
39 func (dw DelegateWrapper) Len() int {
40 return len(dw.delegate)
42 func (dw DelegateWrapper) Swap(i, j int) {
43 dw.delegate[i], dw.delegate[j] = dw.delegate[j], dw.delegate[i]
45 func (dw DelegateWrapper) Less(i, j int) bool {
46 return dw.by(&dw.delegate[i], &dw.delegate[j])
49 type DelegateInfo struct {
50 Delegates []Delegate `json:"delegates"`
53 func (d *DelegateInfo) ConsensusName() string {
57 const maxConfirmBlockCount = 2
59 type IrreversibleBlockInfo struct {
62 HeightHash map[int64]bc.Hash
65 func newIrreversibleBlockInfo() *IrreversibleBlockInfo {
66 o := &IrreversibleBlockInfo{}
67 for i := 0; i < maxConfirmBlockCount; i++ {
68 o.heights = append(o.heights, -1)
69 o.hashs = append(o.hashs, bc.Hash{})
71 o.HeightHash = make(map[int64]bc.Hash)
75 type DposType struct {
78 MaxDelegateNumber uint64
79 BlockIntervalTime uint64
80 DposStartHeight uint64
82 superForgerAddress common.Address
83 irreversibleBlockFileName string
84 irreversibleBlockInfo IrreversibleBlockInfo
85 lockIrreversibleBlockInfo sync.Mutex
86 maxIrreversibleCount int
87 firstIrreversibleThreshold uint64
88 secondIrreversibleThreshold uint64
91 var GDpos = &DposType{
92 maxIrreversibleCount: 10000,
93 firstIrreversibleThreshold: 90,
94 secondIrreversibleThreshold: 67,
97 func (d *DposType) Init(c chain.Chain, delegateNumber, intervalTime, blockHeight uint64, blockHash bc.Hash) error {
99 vote, err := newVote(blockHeight, blockHash)
104 d.MaxDelegateNumber = delegateNumber
105 d.BlockIntervalTime = intervalTime
106 d.DposStartHeight = 0
107 address, _ := common.DecodeAddress("vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep", &consensus.ActiveNetParams)
108 d.superForgerAddress = address
110 GDpos.irreversibleBlockFileName = filepath.Join(config.CommonConfig.RootDir, "dpos", "irreversible_block.dat")
111 GDpos.irreversibleBlockInfo = *newIrreversibleBlockInfo()
112 GDpos.ReadIrreversibleBlockInfo(&GDpos.irreversibleBlockInfo)
113 header, _ := c.GetHeaderByHeight(d.DposStartHeight)
114 d.setStartTime(header.Timestamp)
118 func (d *DposType) setStartTime(t uint64) {
122 func (d *DposType) IsMining(address common.Address, t uint64) (interface{}, error) {
124 header := d.c.BestBlockHeader()
125 currentLoopIndex := d.GetLoopIndex(t)
126 currentDelegateIndex := d.GetDelegateIndex(t)
127 prevLoopIndex := d.GetLoopIndex(header.Timestamp)
128 prevDelegateIndex := d.GetDelegateIndex(header.Timestamp)
129 if currentLoopIndex > prevLoopIndex {
130 delegateInfo := d.GetNextDelegates(t)
131 cDelegateInfo := delegateInfo.(*DelegateInfo)
132 if uint64(len(cDelegateInfo.Delegates)) < currentDelegateIndex+1 {
133 return nil, errors.New("Out of the block node list")
135 if cDelegateInfo.Delegates[currentDelegateIndex].DelegateAddress == address.EncodeAddress() {
136 return delegateInfo, nil
138 return nil, errors.New("Is not the current mining node")
139 } else if currentLoopIndex == prevLoopIndex && currentDelegateIndex > prevDelegateIndex {
140 currentDelegateInfo, err := d.GetBlockDelegates(header)
144 if currentDelegateIndex+1 > uint64(len(currentDelegateInfo.Delegates)) {
145 return nil, errors.New("Out of the block node list")
146 } else if currentDelegateInfo.Delegates[currentDelegateIndex].DelegateAddress == address.EncodeAddress() {
149 return nil, errors.New("Is not the current mining node")
152 return nil, errors.New("Time anomaly")
156 func (d *DposType) ProcessRegister(delegateAddress string, delegateName string, hash bc.Hash, height uint64) bool {
157 return d.vote.ProcessRegister(delegateAddress, delegateName, hash, height)
160 func (d *DposType) ProcessVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool {
161 return d.vote.ProcessVote(voterAddress, delegates, hash, height)
164 func (d *DposType) ProcessCancelVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool {
165 return d.vote.ProcessCancelVote(voterAddress, delegates, hash, height)
168 func (d *DposType) UpdateAddressBalance(addressBalance []engine.AddressBalance) {
169 d.vote.UpdateAddressBalance(addressBalance)
172 func (d *DposType) GetLoopIndex(time uint64) uint64 {
173 if time < d.DposStartTime {
176 return (time - d.DposStartTime) / (d.MaxDelegateNumber * d.BlockIntervalTime)
179 func (d *DposType) GetDelegateIndex(time uint64) uint64 {
180 if time < d.DposStartTime {
183 return (time - d.DposStartTime) % (d.MaxDelegateNumber * d.BlockIntervalTime) / d.BlockIntervalTime
186 func (d *DposType) GetNextDelegates(t uint64) interface{} {
187 delegates := d.vote.GetTopDelegateInfo(config.CommonConfig.Consensus.MinVoterBalance, d.MaxDelegateNumber-1)
188 delegate := Delegate{
189 DelegateAddress: d.superForgerAddress.EncodeAddress(),
192 delegates = append(delegates, delegate)
193 delegateInfo := DelegateInfo{}
194 delegateInfo.Delegates = SortDelegate(delegates, t)
198 func (d *DposType) GetBlockDelegates(header *types.BlockHeader) (*DelegateInfo, error) {
199 loopIndex := d.GetLoopIndex(header.Timestamp)
201 preHeader, err := d.c.GetHeaderByHash(&header.PreviousBlockHash)
205 if header.Height == d.DposStartHeight || d.GetLoopIndex(preHeader.Timestamp) < loopIndex {
206 block, err := d.c.GetBlockByHeight(header.Height)
210 delegateInfo, err := d.GetBlockDelegate(block)
214 return delegateInfo, nil
220 func (d *DposType) GetBlockDelegate(block *types.Block) (*DelegateInfo, error) {
221 tx := block.Transactions[0]
222 if len(tx.TxData.Inputs) == 1 && tx.TxData.Inputs[0].InputType() == types.CoinbaseInputType {
224 if err := json.Unmarshal(tx.TxData.ReferenceData, msg); err != nil {
227 if msg.Type == vm.OP_DELEGATE {
228 delegateInfo := &DelegateInfoList{}
229 if err := json.Unmarshal(msg.Data, delegateInfo); err != nil {
232 return &delegateInfo.Delegate, nil
236 return nil, errors.New("The first transaction is not a coinbase transaction")
239 func (d *DposType) CheckCoinbase(tx types.TxData, t uint64, Height uint64) error {
241 if err := json.Unmarshal(tx.ReferenceData, msg); err != nil {
244 if msg.Type == vm.OP_DELEGATE {
245 delegateInfo := &DelegateInfoList{}
246 if err := json.Unmarshal(msg.Data, delegateInfo); err != nil {
250 binary.LittleEndian.PutUint64(buf[:], t)
252 if !delegateInfo.Xpub.Verify(buf[:], delegateInfo.SigTime) {
253 return errors.New("CheckBlock CheckCoinbase: Verification signature error")
256 address common.Address
259 address, err = common.NewAddressWitnessPubKeyHash(tx.Outputs[0].ControlProgram[2:], &consensus.ActiveNetParams)
263 derivedPK := delegateInfo.Xpub.PublicKey()
264 pubHash := crypto.Ripemd160(derivedPK)
266 addressDet, err := common.NewAddressWitnessPubKeyHash(pubHash, &consensus.ActiveNetParams)
271 if addressDet.EncodeAddress() == address.EncodeAddress() {
275 return errors.New("CheckBlock CheckCoinbase error")
278 func (d *DposType) CheckBlockHeader(header types.BlockHeader) error {
279 blockT := time.Unix(int64(header.Timestamp), 0)
281 if blockT.Sub(time.Now()).Seconds() > float64(d.BlockIntervalTime) {
282 return errors.New("block time is error")
285 if header.Height > d.DposStartHeight {
286 header, _ := d.c.GetHeaderByHeight(d.DposStartHeight)
287 d.setStartTime(header.Timestamp)
290 preHeader, err := d.c.GetHeaderByHash(&header.PreviousBlockHash)
295 currentLoopIndex := d.GetLoopIndex(header.Timestamp)
296 currentDelegateIndex := d.GetDelegateIndex(header.Timestamp)
297 prevLoopIndex := d.GetLoopIndex(preHeader.Timestamp)
298 prevDelegateIndex := d.GetDelegateIndex(preHeader.Timestamp)
299 if currentLoopIndex > prevLoopIndex ||
300 (currentLoopIndex == prevLoopIndex && currentDelegateIndex > prevDelegateIndex) {
304 return errors.New("DPoS CheckBlockHeader error")
307 func (d *DposType) CheckBlock(block types.Block, fIsCheckDelegateInfo bool) error {
308 if block.Height > d.DposStartHeight {
309 header, _ := d.c.GetHeaderByHeight(d.DposStartHeight)
310 d.setStartTime(header.Timestamp)
313 blockT := time.Unix(int64(block.Timestamp), 0)
314 if blockT.Sub(time.Now()).Seconds() > float64(d.BlockIntervalTime) {
315 return errors.New("block time is error")
317 if err := d.CheckCoinbase(block.Transactions[0].TxData, block.Timestamp, block.Height); err != nil {
321 preBlock, err := d.c.GetBlockByHash(&block.PreviousBlockHash)
326 currentLoopIndex := d.GetLoopIndex(block.Timestamp)
327 currentDelegateIndex := d.GetDelegateIndex(block.Timestamp)
328 prevLoopIndex := d.GetLoopIndex(preBlock.Timestamp)
329 prevDelegateIndex := d.GetDelegateIndex(preBlock.Timestamp)
331 delegateInfo := &DelegateInfo{}
333 if currentLoopIndex < prevLoopIndex {
334 return errors.New("Block time exception")
335 } else if currentLoopIndex > prevLoopIndex {
336 if fIsCheckDelegateInfo {
337 if err := d.CheckBlockDelegate(block); err != nil {
340 d.ProcessIrreversibleBlock(block.Height, block.Hash())
342 delegateInfo, err = d.GetBlockDelegate(&block)
347 if currentDelegateIndex < prevDelegateIndex {
348 return errors.New("Block time exception")
351 delegateInfo, err = d.GetBlockDelegates(&preBlock.BlockHeader)
357 delegateAddress := d.getBlockForgerAddress(block)
358 if currentDelegateIndex < uint64(len(delegateInfo.Delegates)) &&
359 delegateInfo.Delegates[currentDelegateIndex].DelegateAddress == delegateAddress.EncodeAddress() {
363 return fmt.Errorf("CheckBlock GetDelegateID blockhash:%s error", h.String())
366 func (d *DposType) CheckBlockDelegate(block types.Block) error {
367 delegateInfo, err := d.GetBlockDelegate(&block)
371 nextDelegateInfoInterface := d.GetNextDelegates(block.Timestamp)
372 nextDelegateInfo := nextDelegateInfoInterface.(*DelegateInfo)
373 if len(delegateInfo.Delegates) != len(nextDelegateInfo.Delegates) {
374 return errors.New("The delegates num is not correct in block")
376 for index, v := range delegateInfo.Delegates {
377 if v.DelegateAddress != nextDelegateInfo.Delegates[index].DelegateAddress {
378 return errors.New("The delegates address is not correct in block")
385 func (d *DposType) ProcessIrreversibleBlock(height uint64, hash bc.Hash) {
386 d.lockIrreversibleBlockInfo.Lock()
387 defer d.lockIrreversibleBlockInfo.Unlock()
389 for i = maxConfirmBlockCount - 1; i >= 0; i-- {
390 if d.irreversibleBlockInfo.heights[i] < 0 || int64(height) < d.irreversibleBlockInfo.heights[i] {
391 d.irreversibleBlockInfo.heights[i] = -1
393 level := (height - uint64(d.irreversibleBlockInfo.heights[i])) * 100
394 if level >= d.MaxDelegateNumber*d.firstIrreversibleThreshold {
395 d.AddIrreversibleBlock(int64(height), hash)
396 } else if level >= d.MaxDelegateNumber*d.secondIrreversibleThreshold {
397 if i == maxConfirmBlockCount-1 {
398 d.AddIrreversibleBlock(int64(height), hash)
399 for k := 0; k < maxConfirmBlockCount-1; k++ {
400 d.irreversibleBlockInfo.heights[k] = d.irreversibleBlockInfo.heights[k+1]
401 d.irreversibleBlockInfo.hashs[k] = d.irreversibleBlockInfo.hashs[k+1]
403 d.irreversibleBlockInfo.heights[i] = int64(height)
404 d.irreversibleBlockInfo.hashs[i] = hash
407 d.irreversibleBlockInfo.heights[i+1] = int64(height)
408 d.irreversibleBlockInfo.hashs[i+1] = hash
413 for k := 0; k < maxConfirmBlockCount; k++ {
414 d.irreversibleBlockInfo.heights[k] = -1
416 d.irreversibleBlockInfo.heights[0] = int64(height)
417 d.irreversibleBlockInfo.hashs[0] = hash
423 d.irreversibleBlockInfo.heights[0] = int64(height)
424 d.irreversibleBlockInfo.hashs[0] = hash
428 func (d *DposType) getBlockForgerAddress(block types.Block) common.Address {
429 tx := block.Transactions[0].TxData
431 if len(tx.Inputs) == 1 && tx.Inputs[0].InputType() == types.CoinbaseInputType {
432 address, err := common.NewAddressWitnessPubKeyHash(tx.Outputs[0].ControlProgram[2:], &consensus.ActiveNetParams)
434 address, err := common.NewAddressWitnessScriptHash(tx.Outputs[0].ControlProgram[2:], &consensus.ActiveNetParams)
446 func (d *DposType) IsValidBlockCheckIrreversibleBlock(height uint64, hash bc.Hash) error {
447 d.lockIrreversibleBlockInfo.Lock()
448 defer d.lockIrreversibleBlockInfo.Unlock()
450 if h, ok := d.irreversibleBlockInfo.HeightHash[int64(height)]; ok {
452 return fmt.Errorf("invalid block[%d:%s]", height, hash.String())
459 func (d *DposType) ReadIrreversibleBlockInfo(info *IrreversibleBlockInfo) error {
460 f, err := os.Open(d.irreversibleBlockFileName)
465 buf := bufio.NewReader(f)
467 line, err := buf.ReadString('\n')
474 line = strings.TrimSpace(line)
476 var hashString string
477 n, err := fmt.Sscanf(line, "%d;%s\n", &height, &hashString)
478 if err != nil || n != 2 {
479 return errors.New("parse error for ReadIrreversibleBlockInfo ")
482 if err := hash.UnmarshalText([]byte(hashString)); err != nil {
485 d.AddIrreversibleBlock(height, hash)
489 type Int64Slice []int64
491 func (a Int64Slice) Len() int {
494 func (a Int64Slice) Swap(i, j int) {
495 a[i], a[j] = a[j], a[i]
497 func (a Int64Slice) Less(i, j int) bool {
501 func (d *DposType) WriteIrreversibleBlockInfo() error {
502 if len(d.irreversibleBlockInfo.HeightHash) == 0 {
506 f, err := os.Create(d.irreversibleBlockFileName)
511 w := bufio.NewWriter(f)
513 for k := range d.irreversibleBlockInfo.HeightHash {
514 keys = append(keys, k)
517 sort.Sort(Int64Slice(keys))
519 for _, k := range keys {
520 data, _ := d.irreversibleBlockInfo.HeightHash[k].MarshalText()
521 line := fmt.Sprintf("%d;%s\n", k, string(data))
525 if err := w.Flush(); err != nil {
532 func (d *DposType) AddIrreversibleBlock(height int64, hash bc.Hash) {
533 for k, _ := range d.irreversibleBlockInfo.HeightHash {
534 if len(d.irreversibleBlockInfo.HeightHash) > d.maxIrreversibleCount {
535 delete(d.irreversibleBlockInfo.HeightHash, k)
540 d.irreversibleBlockInfo.HeightHash[height] = hash
541 d.vote.DeleteInvalidVote(uint64(height))
544 func (d *DposType) GetSuperForgerAddress() common.Address {
545 return d.superForgerAddress
548 func (d *DposType) GetIrreversibleBlock() {
552 func (d *DposType) GetOldBlockHeight() uint64 {
553 return d.vote.GetOldBlockHeight()
556 func (d *DposType) GetOldBlockHash() bc.Hash {
557 return d.vote.GetOldBlockHash()
560 func (d *DposType) ListDelegates() map[string]string {
561 return d.vote.ListDelegates()
564 func (d *DposType) GetDelegateVotes(delegate string) uint64 {
565 return d.vote.GetDelegateVotes(delegate)
568 func (d *DposType) GetDelegateVoters(delegate string) []string {
569 return d.vote.GetDelegateVoters(delegate)
572 func (d *DposType) GetDelegate(name string) string {
573 return d.vote.GetDelegate(name)
577 func (d *DposType) GetDelegateName(address string) string {
578 return d.vote.GetDelegateName(address)
581 func (d *DposType) GetAddressBalance(address string) uint64 {
582 return d.vote.GetAddressBalance(address)
585 func (d *DposType) GetVotedDelegates(voter string) []string {
586 return d.vote.GetVotedDelegates(voter)
589 func (d *DposType) HaveVote(voter, delegate string) bool {
590 return d.vote.HaveVote(voter, delegate)
593 func (d *DposType) HaveDelegate(name, delegate string) bool {
594 return d.vote.HaveDelegate(name, delegate)
597 func (d *DposType) Finish() error {
598 header := d.c.BestBlockHeader()
599 if err := d.vote.Store(header.Height, header.Hash()); err != nil {
603 if err := d.WriteIrreversibleBlockInfo(); err != nil {
610 func SortDelegate(delegates []Delegate, t uint64) []Delegate {
611 var result []Delegate
612 r := getRand(uint64(len(delegates)), int64(t))
613 for _, i := range r {
614 result = append(result, delegates[i])
619 func getRand(num uint64, seed int64) []uint64 {
622 s := make(map[uint64]bool)
626 if _, ok := s[v]; ok {
631 if uint64(len(r)) >= num {