func GetLiveness
has a cyclomatic complexity of 18 with "high" risk 994// It is important to note that the values returned by the beacon node are not canonical;
995// they are best-effort and based upon a subjective view of the network.
996// A beacon node that was recently started or suffered a network partition may indicate that a validator is not live when it actually is.
997func (s *Server) GetLiveness(w http.ResponseWriter, r *http.Request) { 998 ctx, span := trace.StartSpan(r.Context(), "validator.GetLiveness")
999 defer span.End()
1000
func GetSyncCommitteeDuties
has a cyclomatic complexity of 24 with "high" risk 861// or an epoch from the next sync committee period, then get the current state.
862// - Get the state's current sync committee. If it's an epoch from the next sync committee period, then get the next sync committee.
863// - Get duties.
864func (s *Server) GetSyncCommitteeDuties(w http.ResponseWriter, r *http.Request) { 865 ctx, span := trace.StartSpan(r.Context(), "validator.GetSyncCommitteeDuties")
866 defer span.End()
867
func GetProposerDuties
has a cyclomatic complexity of 20 with "high" risk 734}
735
736// GetProposerDuties requests beacon node to provide all validators that are scheduled to propose a block in the given epoch.
737func (s *Server) GetProposerDuties(w http.ResponseWriter, r *http.Request) { 738 ctx, span := trace.StartSpan(r.Context(), "validator.GetProposerDuties")
739 defer span.End()
740
func GetAttesterDuties
has a cyclomatic complexity of 21 with "high" risk 605
606// GetAttesterDuties requests the beacon node to provide a set of attestation duties,
607// which should be performed by validators, for a particular epoch.
608func (s *Server) GetAttesterDuties(w http.ResponseWriter, r *http.Request) { 609 ctx, span := trace.StartSpan(r.Context(), "validator.GetAttesterDuties")
610 defer span.End()
611
func SubmitBeaconCommitteeSubscription
has a cyclomatic complexity of 18 with "high" risk 308
309// SubmitBeaconCommitteeSubscription searches using discv5 for peers related to the provided subnet information
310// and replaces current peers with those ones if necessary.
311func (s *Server) SubmitBeaconCommitteeSubscription(w http.ResponseWriter, r *http.Request) { 312 ctx, span := trace.StartSpan(r.Context(), "validator.SubmitBeaconCommitteeSubscription")
313 defer span.End()
314
func SubmitSyncCommitteeSubscription
has a cyclomatic complexity of 18 with "high" risk 198// Subscribing to sync committee subnets is an action performed by VC to enable
199// network participation, and only required if the VC has an active
200// validator in an active sync committee.
201func (s *Server) SubmitSyncCommitteeSubscription(w http.ResponseWriter, r *http.Request) { 202 ctx, span := trace.StartSpan(r.Context(), "validator.SubmitSyncCommitteeSubscription")
203 defer span.End()
204
func ProcessSlots
has a cyclomatic complexity of 29 with "very-high" risk185// if (state.slot + 1) % SLOTS_PER_EPOCH == 0:
186// process_epoch(state)
187// state.slot = Slot(state.slot + 1)
188func ProcessSlots(ctx context.Context, state state.BeaconState, slot primitives.Slot) (state.BeaconState, error) {189 ctx, span := trace.StartSpan(ctx, "core.state.ProcessSlots")
190 defer span.End()
191 if state == nil || state.IsNil() {
func CommitteeAssignments
has a cyclomatic complexity of 16 with "high" risk158// 2. Compute all committees.
159// 3. Determine the attesting slot for each committee.
160// 4. Construct a map of validator indices pointing to the respective committees.
161func CommitteeAssignments(162 ctx context.Context,
163 state state.BeaconState,
164 epoch primitives.Epoch,
func StartFromSavedState
has a cyclomatic complexity of 19 with "high" risk260}
261
262// StartFromSavedState initializes the blockchain using a previously saved finalized checkpoint.
263func (s *Service) StartFromSavedState(saved state.BeaconState) error {264 log.Info("Blockchain data already exists in DB, initializing...")
265 s.genesisTime = time.Unix(int64(saved.GenesisTime()), 0) // lint:ignore uintcast -- Genesis time will not exceed int64 in your lifetime.
266 s.cfg.AttService.SetGenesisTime(saved.GenesisTime())
A function with high cyclomatic complexity can be hard to understand and maintain. Cyclomatic complexity is a software metric that measures the number of independent paths through a function. A higher cyclomatic complexity indicates that the function has more decision points and is more complex.
Functions with high cyclomatic complexity are more likely to have bugs and be harder to test. They may lead to reduced code maintainability and increased development time.
To reduce the cyclomatic complexity of a function, you can:
- Break the function into smaller, more manageable functions.
- Refactor complex logic into separate functions or classes.
- Avoid multiple return paths and deeply nested control expressions.
Bad practice
package main
import "log"
func fizzbuzzfuzz(x int) { // cc = 1
if x == 0 || x < 0 { // cc = 3 (if, ||)
return
}
for i := 1; i <= x; i++ { // cc = 4 (for)
switch i % 15 * 2 {
case 0: // cc = 5 (case)
countDiv3 += 1
countDiv5 += 1
log.Println("fizzbuzz")
break
case 3:
case 6:
case 9:
case 12: // cc = 9 (case)
countDiv3 += 1
log.Println("fizz")
break
case 5:
case 10: // cc = 11 (case)
countDiv5 += 1
log.Println("buzz")
break
default:
log.Printf("%d\n", x)
}
}
} // CC == 11; raises issues
Recommended
package main
import "log"
func fizzbuzz(x int) { // cc = 1
for i := 1; i <= x; i++ { // cc = 2 (for)
y := i%3 == 0
z := i%5 == 0
if y == z { // 3
if y == false { // 4
log.Printf("%d\n", i)
} else {
log.Println("fizzbuzz")
}
} else {
if y { // 5
log.Println("fizz")
} else {
log.Println("buzz")
}
}
}
} // CC == 5
Issue configuration
Cyclomatic complexity threshold can be configured using the
cyclomatic_complexity_threshold
(docs) in the
.deepsource.toml
config file.
Configuring this is optional. If you don't provide a value, the Analyzer will
raise issues for functions with complexity higher than the default threshold,
which is medium
(only raise issues for >15) for the Go Analyzer.
Here's the mapping of the risk category to the cyclomatic complexity score to help you configure this better:
Risk category | Cyclomatic complexity range | Recommended action |
---|---|---|
low | 1-5 | No action needed. |
medium | 6-15 | Review and monitor. |
high | 16-25 | Review and refactor. Recommended to add comments if the function is absolutely needed to be kept as it is. |
very-high. | 26-50 | Refactor to reduce the complexity. |
critical | >50 | Must refactor this. This can make the code untestable and very difficult to understand. |