github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/network/slashing/consumer.go (about) 1 package slashing 2 3 import ( 4 "fmt" 5 6 "github.com/rs/zerolog" 7 8 "github.com/onflow/flow-go/model/flow" 9 "github.com/onflow/flow-go/module" 10 "github.com/onflow/flow-go/network" 11 "github.com/onflow/flow-go/network/alsp" 12 "github.com/onflow/flow-go/utils/logging" 13 ) 14 15 const ( 16 unknown = "unknown" 17 ) 18 19 // Consumer is a struct that logs a message for any slashable offenses. 20 // This struct will be updated in the future when slashing is implemented. 21 type Consumer struct { 22 log zerolog.Logger 23 metrics module.NetworkSecurityMetrics 24 misbehaviorReportConsumer network.MisbehaviorReportConsumer 25 } 26 27 // NewSlashingViolationsConsumer returns a new Consumer. 28 func NewSlashingViolationsConsumer(log zerolog.Logger, metrics module.NetworkSecurityMetrics, misbehaviorReportConsumer network.MisbehaviorReportConsumer) *Consumer { 29 return &Consumer{ 30 log: log.With().Str("module", "network_slashing_consumer").Logger(), 31 metrics: metrics, 32 misbehaviorReportConsumer: misbehaviorReportConsumer, 33 } 34 } 35 36 // logOffense logs the slashing violation with details. 37 func (c *Consumer) logOffense(misbehavior network.Misbehavior, violation *network.Violation) { 38 // if violation fails before the message is decoded the violation.MsgType will be unknown 39 if len(violation.MsgType) == 0 { 40 violation.MsgType = unknown 41 } 42 43 // if violation fails for an unknown peer violation.Identity will be nil 44 role := unknown 45 nodeID := flow.ZeroID 46 if violation.Identity != nil { 47 role = violation.Identity.Role.String() 48 nodeID = violation.Identity.NodeID 49 } 50 51 e := c.log.Error(). 52 Str("peer_id", violation.PeerID). 53 Str("misbehavior", misbehavior.String()). 54 Str("message_type", violation.MsgType). 55 Str("channel", violation.Channel.String()). 56 Str("protocol", violation.Protocol.String()). 57 Bool(logging.KeySuspicious, true). 58 Str("role", role). 59 Hex("sender_id", logging.ID(nodeID)) 60 61 e.Msg(fmt.Sprintf("potential slashable offense: %s", violation.Err)) 62 63 // capture unauthorized message count metric 64 c.metrics.OnUnauthorizedMessage(role, violation.MsgType, violation.Channel.String(), misbehavior.String()) 65 } 66 67 // reportMisbehavior reports the slashing violation to the alsp misbehavior report manager. When violation identity 68 // is nil this indicates the misbehavior occurred either on a public network and the identity of the sender is unknown 69 // we can skip reporting the misbehavior. 70 // Args: 71 // - misbehavior: the network misbehavior. 72 // - violation: the slashing violation. 73 // Any error encountered while creating the misbehavior report is considered irrecoverable and will result in a fatal log. 74 func (c *Consumer) reportMisbehavior(misbehavior network.Misbehavior, violation *network.Violation) { 75 if violation.Identity == nil { 76 c.log.Debug(). 77 Bool(logging.KeySuspicious, true). 78 Str("peerID", violation.PeerID). 79 Msg("violation identity unknown (or public) skipping misbehavior reporting") 80 c.metrics.OnViolationReportSkipped() 81 return 82 } 83 report, err := alsp.NewMisbehaviorReport(violation.Identity.NodeID, misbehavior) 84 if err != nil { 85 // failing to create the misbehavior report is unlikely. If an error is encountered while 86 // creating the misbehavior report it indicates a bug and processing can not proceed. 87 c.log.Fatal(). 88 Err(err). 89 Str("peerID", violation.PeerID). 90 Msg("failed to create misbehavior report") 91 } 92 c.misbehaviorReportConsumer.ReportMisbehaviorOnChannel(violation.Channel, report) 93 } 94 95 // OnUnAuthorizedSenderError logs an error for unauthorized sender error and reports a misbehavior to alsp misbehavior report manager. 96 func (c *Consumer) OnUnAuthorizedSenderError(violation *network.Violation) { 97 c.logOffense(alsp.UnAuthorizedSender, violation) 98 c.reportMisbehavior(alsp.UnAuthorizedSender, violation) 99 } 100 101 // OnUnknownMsgTypeError logs an error for unknown message type error and reports a misbehavior to alsp misbehavior report manager. 102 func (c *Consumer) OnUnknownMsgTypeError(violation *network.Violation) { 103 c.logOffense(alsp.UnknownMsgType, violation) 104 c.reportMisbehavior(alsp.UnknownMsgType, violation) 105 } 106 107 // OnInvalidMsgError logs an error for messages that contained payloads that could not 108 // be unmarshalled into the message type denoted by message code byte and reports a misbehavior to alsp misbehavior report manager. 109 func (c *Consumer) OnInvalidMsgError(violation *network.Violation) { 110 c.logOffense(alsp.InvalidMessage, violation) 111 c.reportMisbehavior(alsp.InvalidMessage, violation) 112 } 113 114 // OnSenderEjectedError logs an error for sender ejected error and reports a misbehavior to alsp misbehavior report manager. 115 func (c *Consumer) OnSenderEjectedError(violation *network.Violation) { 116 c.logOffense(alsp.SenderEjected, violation) 117 c.reportMisbehavior(alsp.SenderEjected, violation) 118 } 119 120 // OnUnauthorizedUnicastOnChannel logs an error for messages unauthorized to be sent via unicast and reports a misbehavior to alsp misbehavior report manager. 121 func (c *Consumer) OnUnauthorizedUnicastOnChannel(violation *network.Violation) { 122 c.logOffense(alsp.UnauthorizedUnicastOnChannel, violation) 123 c.reportMisbehavior(alsp.UnauthorizedUnicastOnChannel, violation) 124 } 125 126 // OnUnauthorizedPublishOnChannel logs an error for messages unauthorized to be sent via pubsub. 127 func (c *Consumer) OnUnauthorizedPublishOnChannel(violation *network.Violation) { 128 c.logOffense(alsp.UnauthorizedPublishOnChannel, violation) 129 c.reportMisbehavior(alsp.UnauthorizedPublishOnChannel, violation) 130 } 131 132 // OnUnexpectedError logs an error for unexpected errors. This indicates message validation 133 // has failed for an unknown reason and could potentially be n slashable offense and reports a misbehavior to alsp misbehavior report manager. 134 func (c *Consumer) OnUnexpectedError(violation *network.Violation) { 135 c.logOffense(alsp.UnExpectedValidationError, violation) 136 c.reportMisbehavior(alsp.UnExpectedValidationError, violation) 137 }