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 }