github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/network/alsp/report.go (about)

     1  package alsp
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/onflow/flow-go/model/flow"
     7  	"github.com/onflow/flow-go/network"
     8  	"github.com/onflow/flow-go/network/alsp/model"
     9  )
    10  
    11  // MisbehaviorReport is a report that is sent to the networking layer to penalize the misbehaving node.
    12  // A MisbehaviorReport reports the misbehavior of a node on sending a message to the current node that appears valid
    13  // based on the networking layer but is considered invalid by the current node based on the Flow protocol.
    14  //
    15  // A MisbehaviorReport consists of a reason and a penalty. The reason is a string that describes the misbehavior.
    16  // The penalty is a value that is deducted from the overall score of the misbehaving node. The score is
    17  // decayed at each decay interval. If the overall penalty of the misbehaving node drops below the disallow-listing
    18  // threshold, the node is reported to be disallow-listed by the networking layer, i.e., existing connections to the
    19  // node are closed and the node is no longer allowed to connect till its penalty is decayed back to zero.
    20  type MisbehaviorReport struct {
    21  	id      flow.Identifier     // the ID of the misbehaving node
    22  	reason  network.Misbehavior // the reason of the misbehavior
    23  	penalty float64             // the penalty value of the misbehavior
    24  }
    25  
    26  var _ network.MisbehaviorReport = (*MisbehaviorReport)(nil)
    27  
    28  // MisbehaviorReportOpt is an option that can be used to configure a misbehavior report.
    29  type MisbehaviorReportOpt func(r *MisbehaviorReport) error
    30  
    31  // WithPenaltyAmplification returns an option that can be used to amplify the penalty value.
    32  // The penalty value is multiplied by the given value. The value should be between 1-100.
    33  // If the value is not in the range, an error is returned.
    34  // The returned error by this option indicates that the option is not applied. In BFT setup, the returned error
    35  // should be treated as a fatal error.
    36  func WithPenaltyAmplification(v float64) MisbehaviorReportOpt {
    37  	return func(r *MisbehaviorReport) error {
    38  		if v <= 0 || v > 100 {
    39  			return fmt.Errorf("penalty value should be between 1-100: %v", v)
    40  		}
    41  		r.penalty *= v
    42  		return nil
    43  	}
    44  }
    45  
    46  // OriginId returns the ID of the misbehaving node.
    47  func (r MisbehaviorReport) OriginId() flow.Identifier {
    48  	return r.id
    49  }
    50  
    51  // Reason returns the reason of the misbehavior.
    52  func (r MisbehaviorReport) Reason() network.Misbehavior {
    53  	return r.reason
    54  }
    55  
    56  // Penalty returns the penalty value of the misbehavior.
    57  func (r MisbehaviorReport) Penalty() float64 {
    58  	return r.penalty
    59  }
    60  
    61  // NewMisbehaviorReport creates a new misbehavior report with the given reason and options.
    62  // If no options are provided, the default penalty value is used.
    63  // The returned error by this function indicates that the report is not created. In BFT setup, the returned error
    64  // should be treated as a fatal error.
    65  // The default penalty value is 0.01 * misbehaviorDisallowListingThreshold = -86.4
    66  func NewMisbehaviorReport(misbehavingId flow.Identifier, reason network.Misbehavior, opts ...MisbehaviorReportOpt) (*MisbehaviorReport, error) {
    67  	m := &MisbehaviorReport{
    68  		id:      misbehavingId,
    69  		reason:  reason,
    70  		penalty: model.DefaultPenaltyValue,
    71  	}
    72  
    73  	for _, opt := range opts {
    74  		if err := opt(m); err != nil {
    75  			return nil, fmt.Errorf("failed to apply misbehavior report option: %w", err)
    76  		}
    77  	}
    78  
    79  	return m, nil
    80  }