github.com/aergoio/aergo@v1.3.1/consensus/impl/raftv2/config.go (about) 1 package raftv2 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 "time" 8 9 "github.com/aergoio/aergo/message" 10 "github.com/aergoio/aergo/p2p/p2pkey" 11 "github.com/aergoio/aergo/types" 12 13 "github.com/aergoio/aergo/chain" 14 "github.com/aergoio/aergo/config" 15 "github.com/aergoio/aergo/consensus" 16 ) 17 18 var ( 19 ErrEmptyBPs = errors.New("BP list is empty") 20 ErrNotIncludedRaftMember = errors.New("this node isn't included in initial raft members") 21 ErrDupBP = errors.New("raft bp description is duplicated") 22 ErrInvalidRaftPeerID = errors.New("peerID of current raft bp is not equals to p2p configure") 23 ) 24 25 const ( 26 slotQueueMax = 100 27 28 DefaultBlockFactoryTickMs = 100 29 MinBlockFactoryTickMs = 10 30 DefaultTickMS = time.Millisecond * 50 31 DefaultElectionTickCount = 10 32 DefaultSlowNodeGap = 100 33 DefaultSnapFrequency = 30 34 ) 35 36 var ( 37 RaftTick = DefaultTickMS 38 // blockIntervalMs is the block genration interval in milli-seconds. 39 RaftSkipEmptyBlock = false 40 //MaxCommitQueueLen = DefaultCommitQueueLen 41 42 BlockFactoryTickMs time.Duration 43 BlockIntervalMs time.Duration 44 45 ConfSnapFrequency uint64 = DefaultSnapFrequency 46 ConfSnapshotCatchUpEntriesN uint64 = ConfSnapFrequency 47 48 ElectionTickCount = DefaultElectionTickCount 49 MaxSlowNodeGap uint64 = DefaultSlowNodeGap // Criteria for determining whether the server is in a slow state 50 StopDupCommit = false 51 ) 52 53 func Init(raftCfg *config.RaftConfig) { 54 var tickMs time.Duration 55 56 //set default 57 if raftCfg.HeartbeatTick != 0 { 58 RaftTick = time.Duration(raftCfg.HeartbeatTick * 1000000) 59 } 60 61 if raftCfg.ElectionTickCount > 0 { 62 ElectionTickCount = raftCfg.ElectionTickCount 63 } 64 65 if raftCfg.SnapFrequency != 0 { 66 ConfSnapFrequency = raftCfg.SnapFrequency 67 ConfSnapshotCatchUpEntriesN = raftCfg.SnapFrequency 68 } 69 70 if raftCfg.BlockFactoryTickMs != 0 { 71 if raftCfg.BlockFactoryTickMs < MinBlockFactoryTickMs { 72 tickMs = MinBlockFactoryTickMs 73 } else { 74 tickMs = time.Duration(raftCfg.BlockFactoryTickMs) 75 } 76 } else { 77 tickMs = DefaultBlockFactoryTickMs 78 } 79 80 BlockFactoryTickMs = time.Millisecond * tickMs 81 82 if raftCfg.BlockIntervalMs != 0 { 83 BlockIntervalMs = time.Millisecond * time.Duration(raftCfg.BlockIntervalMs) 84 } else { 85 BlockIntervalMs = consensus.BlockInterval 86 } 87 88 if raftCfg.SlowNodeGap > 0 { 89 MaxSlowNodeGap = uint64(raftCfg.SlowNodeGap) 90 } 91 92 if raftCfg.StopDupCommit { 93 StopDupCommit = true 94 } 95 logger.Info().Int64("factory tick(ms)", BlockFactoryTickMs.Nanoseconds()/int64(time.Millisecond)). 96 Int64("interval(ms)", BlockIntervalMs.Nanoseconds()/int64(time.Millisecond)).Msg("set block factory tick/interval") 97 } 98 99 func (bf *BlockFactory) InitCluster(cfg *config.Config) error { 100 var err error 101 102 genesis := chain.Genesis 103 104 raftConfig := cfg.Consensus.Raft 105 if raftConfig == nil { 106 panic("raftconfig is not set. please set raftName, raftBPs.") 107 } 108 109 chainID, err := genesis.ID.Bytes() 110 if err != nil { 111 return err 112 } 113 114 bf.bpc = NewCluster(chainID, bf, raftConfig.Name, p2pkey.NodeID(), genesis.Timestamp, func(event *message.RaftClusterEvent) { bf.Tell(message.P2PSvc, event) }) 115 116 if raftConfig.NewCluster { 117 var mbrAttrs []*types.MemberAttr 118 var ebps []types.EnterpriseBP 119 120 if !raftConfig.UseBackup { 121 ebps = chain.Genesis.EnterpriseBPs 122 } else { 123 ebps = getRecoverBp(raftConfig) 124 } 125 126 if mbrAttrs, err = parseBpsToMembers(ebps); err != nil { 127 logger.Error().Err(err).Bool("usebackup", raftConfig.UseBackup).Msg("failed to parse initial bp list") 128 return err 129 } 130 131 if err = bf.bpc.AddInitialMembers(mbrAttrs); err != nil { 132 logger.Error().Err(err).Msg("failed to add initial members") 133 return err 134 } 135 } 136 137 RaftSkipEmptyBlock = raftConfig.SkipEmpty 138 139 logger.Info().Bool("skipempty", RaftSkipEmptyBlock).Int64("rafttick(nanosec)", RaftTick.Nanoseconds()).Float64("interval(sec)", consensus.BlockInterval.Seconds()).Msg(bf.bpc.toString()) 140 141 return nil 142 } 143 144 // getRecoverBp returns Enterprise BP to use initial bp of new cluster for recovery from backup 145 func getRecoverBp(raftConfig *config.RaftConfig) []types.EnterpriseBP { 146 if raftConfig.RecoverBP == nil { 147 logger.Fatal().Msg("need RecoverBP in config to create a new cluster") 148 } 149 150 cfgBP := raftConfig.RecoverBP 151 return []types.EnterpriseBP{{Name: cfgBP.Name, Address: cfgBP.Address, PeerID: cfgBP.PeerID}} 152 } 153 154 func parseBpsToMembers(bps []types.EnterpriseBP) ([]*types.MemberAttr, error) { 155 bpLen := len(bps) 156 if bpLen == 0 { 157 return nil, ErrEmptyBPs 158 } 159 160 mbrs := make([]*types.MemberAttr, bpLen) 161 for i, bp := range bps { 162 trimmedAddr := strings.TrimSpace(bp.Address) 163 // TODO when p2p is applied, have to validate peer address 164 if _, err := types.ParseMultiaddrWithResolve(trimmedAddr); err != nil { 165 return nil, err 166 } 167 168 peerID, err := types.IDB58Decode(bp.PeerID) 169 if err != nil { 170 return nil, fmt.Errorf("invalid raft peerID BP[%d]:%s", i, bp.PeerID) 171 } 172 173 mbrs[i] = &types.MemberAttr{Name: bp.Name, Address: trimmedAddr, PeerID: []byte(peerID)} 174 } 175 176 return mbrs, nil 177 } 178 179 func (cl *Cluster) AddInitialMembers(mbrs []*types.MemberAttr) error { 180 logger.Debug().Msg("add cluster members from config file") 181 182 for _, mbrAttr := range mbrs { 183 m := consensus.NewMember(mbrAttr.Name, mbrAttr.Address, types.PeerID(mbrAttr.PeerID), cl.chainID, cl.chainTimestamp) 184 185 if err := cl.isValidMember(m); err != nil { 186 return err 187 } 188 if err := cl.addMember(m, false); err != nil { 189 return err 190 } 191 } 192 193 if cl.Members().len() == 0 { 194 logger.Fatal().Str("cluster", cl.toString()).Msg("can't start raft server because there are no members in cluster") 195 } 196 197 if cl.Members().getMemberByName(cl.NodeName()) == nil { 198 logger.Fatal().Str("cluster", cl.toString()).Msg("node name of config is not included in genesis block") 199 } 200 201 return nil 202 } 203 204 func (cl *Cluster) SetThisNodeID() error { 205 cl.Lock() 206 defer cl.Unlock() 207 208 var member *consensus.Member 209 210 if member = cl.Members().getMemberByName(cl.NodeName()); member == nil { 211 return ErrNotIncludedRaftMember 212 } 213 214 // it can be reset when this node is added to cluster 215 cl.SetNodeID(member.ID) 216 217 return nil 218 }