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  }