func GenerateFullBlock
has a cyclomatic complexity of 21 with "high" risk 79
80// GenerateFullBlock generates a fully valid block with the requested parameters.
81// Use BlockGenConfig to declare the conditions you would like the block generated under.
82func GenerateFullBlock( 83 bState state.BeaconState,
84 privs []bls.SecretKey,
85 conf *BlockGenConfig,
func Proto
has a cyclomatic complexity of 23 with "high" risk 285}
286
287// Proto converts the beacon block body to a protobuf object.
288func (b *BeaconBlockBody) Proto() (proto.Message, error) { 289 if b == nil {
290 return nil, nil
291 }
func Proto
has a cyclomatic complexity of 28 with "very-high" risk 137}
138
139// Proto converts the beacon block to a protobuf object.
140func (b *BeaconBlock) Proto() (proto.Message, error) { 141 if b == nil {
142 return nil, nil
143 }
func Proto
has a cyclomatic complexity of 28 with "very-high" risk 13)
14
15// Proto converts the signed beacon block to a protobuf object.
16func (b *SignedBeaconBlock) Proto() (proto.Message, error) { 17 if b == nil {
18 return nil, errNilBlock
19 }
func BuildSignedBeaconBlockFromExecutionPayload
has a cyclomatic complexity of 22 with "high" risk210
211// BuildSignedBeaconBlockFromExecutionPayload takes a signed, blinded beacon block and converts into
212// a full, signed beacon block by specifying an execution payload.
213func BuildSignedBeaconBlockFromExecutionPayload(214 blk interfaces.ReadOnlySignedBeaconBlock, payload interface{},
215) (interfaces.SignedBeaconBlock, error) {
216 if err := BeaconBlockIsNil(blk); err != nil {
func BuildSignedBeaconBlock
has a cyclomatic complexity of 19 with "high" risk145// BuildSignedBeaconBlock assembles a block.ReadOnlySignedBeaconBlock interface compatible struct from a
146// given beacon block and the appropriate signature. This method may be used to easily create a
147// signed beacon block.
148func BuildSignedBeaconBlock(blk interfaces.ReadOnlyBeaconBlock, signature []byte) (interfaces.SignedBeaconBlock, error) {149 pb, err := blk.Proto()
150 if err != nil {
151 return nil, err
func NewBeaconBlock
has a cyclomatic complexity of 19 with "high" risk 75}
76
77// NewBeaconBlock creates a beacon block from a protobuf beacon block.
78func NewBeaconBlock(i interface{}) (interfaces.ReadOnlyBeaconBlock, error) { 79 switch b := i.(type) {
80 case nil:
81 return nil, ErrNilObject
func NewSignedBeaconBlock
has a cyclomatic complexity of 20 with "high" risk 31)
32
33// NewSignedBeaconBlock creates a signed beacon block from a protobuf signed beacon block.
34func NewSignedBeaconBlock(i interface{}) (interfaces.SignedBeaconBlock, error) { 35 switch b := i.(type) {
36 case nil:
37 return nil, ErrNilObject
func IsEmptyExecutionData
has a cyclomatic complexity of 19 with "high" risk 900
901// IsEmptyExecutionData checks if an execution data is empty underneath. If a single field has
902// a non-zero value, this function will return false.
903func IsEmptyExecutionData(data interfaces.ExecutionData) (bool, error) { 904 if data == nil {
905 return true, nil
906 }
func rootSelector
has a cyclomatic complexity of 41 with "very-high" risk1118 return b == nil
1119}
1120
1121func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex) ([32]byte, error) {1122 _, span := trace.StartSpan(ctx, "beaconState.rootSelector")
1123 defer span.End()
1124 span.AddAttributes(trace.StringAttribute("field", field.String()))
func Copy
has a cyclomatic complexity of 28 with "very-high" risk 802}
803
804// Copy returns a deep copy of the beacon state.
805func (b *BeaconState) Copy() state.BeaconState { 806 b.lock.RLock()
807 defer b.lock.RUnlock()
808
func TestGetSpec
has a cyclomatic complexity of 150 with "critical" risk 40 assert.Equal(t, "0x4242424242424242424242424242424242424242", response.Data.Address)
41}
42
43func TestGetSpec(t *testing.T) { 44 params.SetupTestConfigCleanup(t)
45 config := params.BeaconConfig().Copy()
46
func ProcessBlockForStateRoot
has a cyclomatic complexity of 16 with "high" risk282// process_eth1_data(state, block.body)
283// process_operations(state, block.body)
284// process_sync_aggregate(state, block.body.sync_aggregate)
285func ProcessBlockForStateRoot(286 ctx context.Context,
287 state state.BeaconState,
288 signed interfaces.ReadOnlySignedBeaconBlock,
func ProcessExecutionLayerWithdrawalRequest
has a cyclomatic complexity of 30 with "very-high" risk332// amount=to_withdraw,
333// withdrawable_epoch=withdrawable_epoch,
334// ))
335func ProcessExecutionLayerWithdrawalRequest(ctx context.Context,336 beaconState state.BeaconState, beaconBlock interfaces.ReadOnlyBeaconBlock) (state.BeaconState, error) {
337 if beaconState.Version() < version.Electra || beaconBlock.Version() < version.Electra {
338 return beaconState, nil
func ProcessWithdrawals
has a cyclomatic complexity of 16 with "high" risk148// next_index = state.next_withdrawal_validator_index + MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP
149// next_validator_index = ValidatorIndex(next_index % len(state.validators))
150// state.next_withdrawal_validator_index = next_validator_index
151func ProcessWithdrawals(st state.BeaconState, executionData interfaces.ExecutionData) (state.BeaconState, error) {152 expectedWithdrawals, err := st.ExpectedWithdrawals()
153 if err != nil {
154 return nil, errors.Wrap(err, "could not get expected withdrawals")
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. |