UNPKG

@lodestar/beacon-node

Version:

A Typescript implementation of the beacon chain

110 lines 5.53 kB
import { TopicValidatorResult } from "@libp2p/interface"; import { AttestationError, GossipAction, GossipActionError } from "../../chain/errors/index.js"; /** * Similar to getGossipValidatorFn but return a function to accept a batch of beacon_attestation messages * with the same attestation data */ export function getGossipValidatorBatchFn(gossipHandlers, modules) { const { logger, metrics } = modules; return async function gossipValidatorBatchFn(messageInfos) { // all messageInfos have same topic type const type = messageInfos[0].topic.type; try { const results = await gossipHandlers[type](messageInfos.map((messageInfo) => ({ gossipData: { serializedData: messageInfo.msg.data, msgSlot: messageInfo.msgSlot, indexed: messageInfo.indexed, }, topic: messageInfo.topic, peerIdStr: messageInfo.propagationSource, seenTimestampSec: messageInfo.seenTimestampSec, }))); return results.map((e) => { if (e == null) { return TopicValidatorResult.Accept; } if (!(e instanceof AttestationError)) { logger.debug(`Gossip batch validation ${type} threw a non-AttestationError`, {}, e); metrics?.networkProcessor.gossipValidationIgnore.inc({ topic: type }); return TopicValidatorResult.Ignore; } switch (e.action) { case GossipAction.IGNORE: metrics?.networkProcessor.gossipValidationIgnore.inc({ topic: type }); // only beacon_attestation topic is validated in batch metrics?.networkProcessor.gossipAttestationIgnoreByReason.inc({ reason: e.type.code }); return TopicValidatorResult.Ignore; case GossipAction.REJECT: metrics?.networkProcessor.gossipValidationReject.inc({ topic: type }); // only beacon_attestation topic is validated in batch metrics?.networkProcessor.gossipAttestationRejectByReason.inc({ reason: e.type.code }); logger.debug(`Gossip validation ${type} rejected`, {}, e); return TopicValidatorResult.Reject; } }); } catch (e) { // Don't expect error here logger.debug(`Gossip batch validation ${type} threw an error`, {}, e); const results = []; for (let i = 0; i < messageInfos.length; i++) { results.push(TopicValidatorResult.Ignore); } return results; } }; } /** * Returns a GossipSub validator function from a GossipHandlerFn. GossipHandlerFn may throw GossipActionError if one * or more validation conditions from the consensus-specs#p2p-interface are not satisfied. * * This function receives a string topic and a binary message `InMessage` and deserializes both using caches. * - The topic string should be known in advance and pre-computed * - The message.data should already by uncompressed when computing its msgID * * All logging and metrics associated with gossip object validation should happen in this function. We want to know * - In debug logs what objects are we processing, the result and some succint metadata * - In metrics what's the throughput and ratio of accept/ignore/reject per type * * @see getGossipHandlers for reasoning on why GossipHandlerFn are used for gossip validation. */ export function getGossipValidatorFn(gossipHandlers, modules) { const { logger, metrics } = modules; return async function gossipValidatorFn({ topic, msg, propagationSource, seenTimestampSec, msgSlot }) { const type = topic.type; try { await gossipHandlers[type]({ gossipData: { serializedData: msg.data, msgSlot }, topic, peerIdStr: propagationSource, seenTimestampSec, }); metrics?.networkProcessor.gossipValidationAccept.inc({ topic: type }); return TopicValidatorResult.Accept; } catch (e) { if (!(e instanceof GossipActionError)) { // not deserve to log error here, it looks too dangerous to users logger.debug(`Gossip validation ${type} threw a non-GossipActionError`, {}, e); return TopicValidatorResult.Ignore; } // Metrics on specific error reason // Note: LodestarError.code are bounded pre-declared error messages, not from arbitrary error.message metrics?.networkProcessor.gossipValidationError.inc({ topic: type, error: e.type.code, }); switch (e.action) { case GossipAction.IGNORE: metrics?.networkProcessor.gossipValidationIgnore.inc({ topic: type }); return TopicValidatorResult.Ignore; case GossipAction.REJECT: metrics?.networkProcessor.gossipValidationReject.inc({ topic: type }); logger.debug(`Gossip validation ${type} rejected`, {}, e); return TopicValidatorResult.Reject; } } }; } //# sourceMappingURL=gossipValidatorFn.js.map