github.com/iotexproject/iotex-core@v1.14.1-rc1/action/protocol/vote/unproductivedelegate.go (about)

     1  // Copyright (c) 2020 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package vote
     7  
     8  import (
     9  	"sort"
    10  
    11  	"github.com/pkg/errors"
    12  	"google.golang.org/protobuf/proto"
    13  
    14  	updpb "github.com/iotexproject/iotex-core/action/protocol/vote/unproductivedelegatepb"
    15  )
    16  
    17  // UnproductiveDelegate defines unproductive delegates information within probation period
    18  type UnproductiveDelegate struct {
    19  	delegatelist    [][]string
    20  	probationPeriod uint64
    21  	cacheSize       uint64
    22  }
    23  
    24  // NewUnproductiveDelegate creates new UnproductiveDelegate with probationperiod and cacheSize
    25  func NewUnproductiveDelegate(probationPeriod uint64, cacheSize uint64) (*UnproductiveDelegate, error) {
    26  	if probationPeriod > cacheSize {
    27  		return nil, errors.New("cache size of unproductiveDelegate should be bigger than probation period + 1")
    28  	}
    29  	return &UnproductiveDelegate{
    30  		delegatelist:    make([][]string, cacheSize),
    31  		probationPeriod: probationPeriod,
    32  		cacheSize:       cacheSize,
    33  	}, nil
    34  }
    35  
    36  // AddRecentUPD adds new epoch upd-list at the leftmost and shift existing lists to the right
    37  func (upd *UnproductiveDelegate) AddRecentUPD(new []string) error {
    38  	delegates := make([]string, len(new))
    39  	copy(delegates, new)
    40  	sort.Strings(delegates)
    41  	upd.delegatelist = append([][]string{delegates}, upd.delegatelist[0:upd.probationPeriod-1]...)
    42  	if len(upd.delegatelist) > int(upd.probationPeriod) {
    43  		return errors.New("wrong length of UPD delegatelist")
    44  	}
    45  	return nil
    46  }
    47  
    48  // ReadOldestUPD returns the last upd-list
    49  func (upd *UnproductiveDelegate) ReadOldestUPD() []string {
    50  	return upd.delegatelist[upd.probationPeriod-1]
    51  }
    52  
    53  // Serialize serializes unproductvieDelegate struct to bytes
    54  func (upd *UnproductiveDelegate) Serialize() ([]byte, error) {
    55  	return proto.Marshal(upd.Proto())
    56  }
    57  
    58  // Proto converts the unproductvieDelegate struct to a protobuf message
    59  func (upd *UnproductiveDelegate) Proto() *updpb.UnproductiveDelegate {
    60  	delegatespb := make([]*updpb.Delegatelist, 0, len(upd.delegatelist))
    61  	for _, elem := range upd.delegatelist {
    62  		data := make([]string, len(elem))
    63  		copy(data, elem)
    64  		listpb := &updpb.Delegatelist{
    65  			Delegates: data,
    66  		}
    67  		delegatespb = append(delegatespb, listpb)
    68  	}
    69  	return &updpb.UnproductiveDelegate{
    70  		DelegateList:    delegatespb,
    71  		ProbationPeriod: upd.probationPeriod,
    72  		CacheSize:       upd.cacheSize,
    73  	}
    74  }
    75  
    76  // Deserialize deserializes bytes to UnproductiveDelegate struct
    77  func (upd *UnproductiveDelegate) Deserialize(buf []byte) error {
    78  	unproductivedelegatePb := &updpb.UnproductiveDelegate{}
    79  	if err := proto.Unmarshal(buf, unproductivedelegatePb); err != nil {
    80  		return errors.Wrap(err, "failed to unmarshal unproductive delegate")
    81  	}
    82  	return upd.LoadProto(unproductivedelegatePb)
    83  }
    84  
    85  // LoadProto converts protobuf message to unproductvieDelegate struct
    86  func (upd *UnproductiveDelegate) LoadProto(updPb *updpb.UnproductiveDelegate) error {
    87  	var delegates [][]string
    88  	for _, delegatelistpb := range updPb.DelegateList {
    89  		var delegateElem []string
    90  		delegateElem = append(delegateElem, delegatelistpb.Delegates...)
    91  		delegates = append(delegates, delegateElem)
    92  	}
    93  	upd.delegatelist = delegates
    94  	upd.probationPeriod = updPb.ProbationPeriod
    95  	upd.cacheSize = updPb.CacheSize
    96  
    97  	return nil
    98  }
    99  
   100  // Equal compares with other upd struct and returns true if it's equal
   101  func (upd *UnproductiveDelegate) Equal(upd2 *UnproductiveDelegate) bool {
   102  	if upd.probationPeriod != upd2.probationPeriod {
   103  		return false
   104  	}
   105  	if upd.cacheSize != upd2.cacheSize {
   106  		return false
   107  	}
   108  	if len(upd.delegatelist) != len(upd2.delegatelist) {
   109  		return false
   110  	}
   111  	for i, list := range upd.delegatelist {
   112  		for j, str := range list {
   113  			if str != upd2.delegatelist[i][j] {
   114  				return false
   115  			}
   116  		}
   117  	}
   118  	return true
   119  }
   120  
   121  // DelegateList returns delegate list 2D array
   122  func (upd *UnproductiveDelegate) DelegateList() [][]string {
   123  	return upd.delegatelist
   124  }