Repository: paritytech/substrate
File: frame/im-online/src/lib.rs (Rust)

Code before:
	/// heartbeat later on will not be necessary.
	///
	/// This value will only be used as a fallback if we fail to get a proper session
	/// progress estimate from `NextSessionRotation`, as those estimates should be
	/// more accurate then the value we calculate for `HeartbeatAfter`.
	#[pallet::storage]
	#[pallet::getter(fn heartbeat_after)]
	pub(crate) type HeartbeatAfter<T: Config> = StorageValue<_, T::BlockNumber, ValueQuery>;

	/// The current set of keys that may issue a heartbeat.
	#[pallet::storage]
	#[pallet::getter(fn keys)]
	pub(crate) type Keys<T: Config> =
		StorageValue<_, WeakBoundedVec<T::AuthorityId, T::MaxKeys>, ValueQuery>;

	/// For each session index, we keep a mapping of `AuthIndex` to
	/// `offchain::OpaqueNetworkState`.
	#[pallet::storage]
	#[pallet::getter(fn received_heartbeats)]
	pub(crate) type ReceivedHeartbeats<T: Config> = StorageDoubleMap<
		_,
		Twox64Concat,
		SessionIndex,
		Twox64Concat,
		AuthIndex,
		WeakBoundedVec<u8, T::MaxKeys>,
	>;

	/// For each session index, we keep a mapping of `ValidatorId<T>` to the
	/// number of blocks authored by the given authority.
	#[pallet::storage]
	#[pallet::getter(fn authored_blocks)]
	pub(crate) type AuthoredBlocks<T: Config> = StorageDoubleMap<
		_,
		Twox64Concat,
		SessionIndex,
		Twox64Concat,
		ValidatorId<T>,
		u32,
		ValueQuery,
	>;

	#[pallet::genesis_config]
	pub struct GenesisConfig<T: Config> {
		pub keys: Vec<T::AuthorityId>,
	}

	#[cfg(feature = "std")]
	impl<T: Config> Default for GenesisConfig<T> {
		fn default() -> Self {
			GenesisConfig { keys: Default::default() }

Review comment (suggestion):
the value here was a `Vec<u8>` which contains the encoded network state (i.e. an encoded value of type `OpaqueNetworkState`.
So it is no bounded by the max number of keys. We have to find or ask for the bound somewhere else.
It seems to be bounded by the max number of external addresses that the node can be reached at. maybe we can bound it directly in `sp-core::offchain::OpaqueNetworkState` or (and it is easier) ask for the bound in a generic param.

Code after:
		type MaxPeerInHeartbeats: Get<u32>;

		/// The maximum size of the encoding of `PeerId` and `MultiAddr` that are coming
		/// from the hearbeat
		type MaxPeerDataEncodingSize: Get<u32>;

		/// The overarching event type.
		type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;

		/// A type for retrieving the validators supposed to be online in a session.
		type ValidatorSet: ValidatorSetWithIdentification<Self::AccountId>;

		/// A trait that allows us to estimate the current session progress and also the
		/// average session length.
		///
		/// This parameter is used to determine the longevity of `heartbeat` transaction and a
		/// rough time when we should start considering sending heartbeats, since the workers
		/// avoids sending them at the very beginning of the session, assuming there is a
		/// chance the authority will produce a block and they won't be necessary.
		type NextSessionRotation: EstimateNextSessionRotation<Self::BlockNumber>;

		/// A type that gives us the ability to submit unresponsiveness offence reports.
		type ReportUnresponsiveness: ReportOffence<
			Self::AccountId,
			IdentificationTuple<Self>,
			UnresponsivenessOffence<IdentificationTuple<Self>>,
		>;

		/// A configuration for base priority of unsigned transactions.
		///
		/// This is exposed so that it can be tuned for particular runtime, when
		/// multiple pallets send unsigned transactions.
		#[pallet::constant]
		type UnsignedPriority: Get<TransactionPriority>;

		/// Weight information for extrinsics in this pallet.
		type WeightInfo: WeightInfo;
	}

	#[pallet::event]
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
	pub enum Event<T: Config> {
		/// A new heartbeat was received from `AuthorityId` \[authority_id\]
		HeartbeatReceived(T::AuthorityId),
		/// At the end of the session, no offence was committed.
		AllGood,
		/// At the end of the session, at least one validator was found to be \[offline\].
		SomeOffline(Vec<IdentificationTuple<T>>),
	}

	#[pallet::error]