From ff85b402a15e38c285208462cbafa9cb76e77de7 Mon Sep 17 00:00:00 2001 From: Shreyan Gupta Date: Thu, 18 Apr 2024 17:33:50 -0700 Subject: [PATCH 1/3] [stateless_validation] Implement distribution of state witness parts --- .../state_witness_actions.rs | 164 +++++++++++++++--- .../state_witness_actor.rs | 4 + .../state_witness_producer.rs | 6 +- chain/network/src/types.rs | 1 + core/primitives-core/src/version.rs | 5 +- core/primitives/src/stateless_validation.rs | 84 ++++++++- core/primitives/src/validator_signer.rs | 28 ++- 7 files changed, 263 insertions(+), 29 deletions(-) diff --git a/chain/client/src/stateless_validation/state_witness_actions.rs b/chain/client/src/stateless_validation/state_witness_actions.rs index c83814da484..2054bad3eef 100644 --- a/chain/client/src/stateless_validation/state_witness_actions.rs +++ b/chain/client/src/stateless_validation/state_witness_actions.rs @@ -1,14 +1,20 @@ +use std::collections::HashMap; use std::sync::Arc; +use itertools::Itertools; use near_async::messaging::CanSend; use near_async::time::Clock; use near_chain::Error; use near_epoch_manager::EpochManagerAdapter; use near_network::types::{NetworkRequests, PeerManagerAdapter, PeerManagerMessageRequest}; +use near_primitives::checked_feature; +use near_primitives::reed_solomon::ReedSolomonWrapper; +use near_primitives::sharding::ShardChunkHeader; use near_primitives::stateless_validation::{ ChunkStateWitness, ChunkStateWitnessAck, EncodedChunkStateWitness, PartialEncodedStateWitness, SignedEncodedChunkStateWitness, }; +use near_primitives::types::{AccountId, EpochId}; use near_primitives::validator_signer::ValidatorSigner; use crate::metrics; @@ -25,6 +31,9 @@ pub struct StateWitnessActions { epoch_manager: Arc, /// Tracks a collection of state witnesses sent from chunk producers to chunk validators. state_witness_tracker: ChunkStateWitnessTracker, + /// Reed Solomon encoder for encoding state witness parts. + /// We keep one wrapper for each length of chunk_validators to avoid re-creating the encoder. + rs_map: HashMap, } impl StateWitnessActions { @@ -39,6 +48,7 @@ impl StateWitnessActions { my_signer, epoch_manager, state_witness_tracker: ChunkStateWitnessTracker::new(clock), + rs_map: HashMap::new(), } } @@ -46,41 +56,121 @@ impl StateWitnessActions { &mut self, msg: DistributeStateWitnessRequest, ) -> Result<(), Error> { - let DistributeStateWitnessRequest { state_witness } = msg; + let DistributeStateWitnessRequest { epoch_id, chunk_header, state_witness } = msg; - let signed_witness = create_signed_witness(&state_witness, self.my_signer.as_ref())?; - - let mut chunk_validators = self + let chunk_validators = self .epoch_manager .get_chunk_validator_assignments( - &state_witness.epoch_id, - state_witness.chunk_header.shard_id(), - state_witness.chunk_header.height_created(), + &epoch_id, + chunk_header.shard_id(), + chunk_header.height_created(), )? .ordered_chunk_validators(); tracing::debug!( target: "stateless_validation", "Sending chunk state witness for chunk {:?} to chunk validators {:?}", - state_witness.chunk_header.chunk_hash(), + chunk_header.chunk_hash(), chunk_validators, ); + let witness_bytes = compress_witness(&state_witness)?; + // Record the witness in order to match the incoming acks for measuring round-trip times. // See process_chunk_state_witness_ack for the handling of the ack messages. self.state_witness_tracker.record_witness_sent( &state_witness, - signed_witness.witness_bytes.size_bytes(), + witness_bytes.size_bytes(), chunk_validators.len(), ); + let protocol_version = self.epoch_manager.get_epoch_protocol_version(&epoch_id)?; + if !checked_feature!("stable", PartialEncodedStateWitness, protocol_version) { + // TODO(stateless_validation): Deprecate once we send state witness in parts. + self.send_state_witness(witness_bytes, chunk_validators); + } else { + self.send_state_witness_parts(epoch_id, chunk_header, witness_bytes, chunk_validators)?; + } + + Ok(()) + } + + // TODO(stateless_validation): Deprecate once we send state witness in parts. + // This is the original way of sending out state witness where the chunk producer sends the whole witness + // to all chunk validators. + fn send_state_witness( + &self, + witness_bytes: EncodedChunkStateWitness, + mut chunk_validators: Vec, + ) { // Remove ourselves from the list of chunk validators. Network can't send messages to ourselves. chunk_validators.retain(|validator| validator != self.my_signer.validator_id()); + let signed_witness = SignedEncodedChunkStateWitness { + signature: self.my_signer.sign_chunk_state_witness(&witness_bytes), + witness_bytes, + }; + self.network_adapter.send(PeerManagerMessageRequest::NetworkRequests( NetworkRequests::ChunkStateWitness(chunk_validators, signed_witness), )); + } + + // Break the state witness into parts and send each part to the corresponding chunk validator owner. + // The chunk validator owner will then forward the part to all other chunk validators. + // Each chunk validator would collect the parts and reconstruct the state witness. + fn send_state_witness_parts( + &mut self, + epoch_id: EpochId, + chunk_header: ShardChunkHeader, + witness_bytes: EncodedChunkStateWitness, + chunk_validators: Vec, + ) -> Result<(), Error> { + // Break the state witness into parts using Reed Solomon encoding. + let rs = self.rs_map.entry(chunk_validators.len()).or_insert_with(|| { + let total_parts = chunk_validators.len(); + let data_parts = std::cmp::max(total_parts * 2 / 3, 1); + ReedSolomonWrapper::new(data_parts, total_parts - data_parts) + }); + let (parts, encoded_length) = rs.encode(witness_bytes); + + let validator_witness_tuple = chunk_validators + .iter() + .zip_eq(parts) + .enumerate() + .map(|(part_ord, (chunk_validator, part))| { + // It's fine to unwrap part here as we just constructed the parts above and we expect + // all of them to be present. + let partial_witness = PartialEncodedStateWitness::new( + epoch_id.clone(), + chunk_header.clone(), + part_ord, + part.unwrap().to_vec(), + encoded_length, + self.my_signer.as_ref(), + ); + (chunk_validator.clone(), partial_witness) + }) + .collect_vec(); + // Since we can't send network message to ourselves, we need to send the PartialEncodedStateWitnessForward + // message for our part. + if let Some((_, partial_witness)) = validator_witness_tuple + .iter() + .find(|(validator, _)| validator == self.my_signer.validator_id()) + { + self.network_adapter.send(PeerManagerMessageRequest::NetworkRequests( + NetworkRequests::PartialEncodedStateWitnessForward( + chunk_validators, + partial_witness.clone(), + ), + )); + } + + // Send the parts to the corresponding chunk validator owners. + self.network_adapter.send(PeerManagerMessageRequest::NetworkRequests( + NetworkRequests::PartialEncodedStateWitness(validator_witness_tuple), + )); Ok(()) } @@ -98,37 +188,71 @@ impl StateWitnessActions { &self, partial_witness: PartialEncodedStateWitness, ) -> Result<(), Error> { - unimplemented!("{:?}", partial_witness) + // Validate the partial encoded state witness. + self.validate_partial_encoded_state_witness(&partial_witness)?; + + // Store the partial encoded state witness for self. + self.store_partial_encoded_state_witness(&partial_witness)?; + + // Forward the part to all the chunk validators. + let chunk_validators = self + .epoch_manager + .get_chunk_validator_assignments( + partial_witness.epoch_id(), + partial_witness.chunk_header().shard_id(), + partial_witness.chunk_header().height_created(), + )? + .ordered_chunk_validators(); + + self.network_adapter.send(PeerManagerMessageRequest::NetworkRequests( + NetworkRequests::PartialEncodedStateWitnessForward(chunk_validators, partial_witness), + )); + + Ok(()) } /// Function to handle receiving partial_encoded_state_witness_forward message from chunk producer. pub fn handle_partial_encoded_state_witness_forward( &self, partial_witness: PartialEncodedStateWitness, + ) -> Result<(), Error> { + // Validate the partial encoded state witness. + self.validate_partial_encoded_state_witness(&partial_witness)?; + + // Store the partial encoded state witness for self. + self.store_partial_encoded_state_witness(&partial_witness)?; + + Ok(()) + } + + fn validate_partial_encoded_state_witness( + &self, + partial_witness: &PartialEncodedStateWitness, + ) -> Result<(), Error> { + unimplemented!("{:?}", partial_witness) + } + + fn store_partial_encoded_state_witness( + &self, + partial_witness: &PartialEncodedStateWitness, ) -> Result<(), Error> { unimplemented!("{:?}", partial_witness) } } -fn create_signed_witness( - witness: &ChunkStateWitness, - my_signer: &dyn ValidatorSigner, -) -> Result { +fn compress_witness(witness: &ChunkStateWitness) -> Result { let shard_id_label = witness.chunk_header.shard_id().to_string(); let encode_timer = metrics::CHUNK_STATE_WITNESS_ENCODE_TIME .with_label_values(&[shard_id_label.as_str()]) .start_timer(); let (witness_bytes, raw_witness_size) = EncodedChunkStateWitness::encode(&witness)?; encode_timer.observe_duration(); - let signed_witness = SignedEncodedChunkStateWitness { - signature: my_signer.sign_chunk_state_witness(&witness_bytes), - witness_bytes, - }; + metrics::CHUNK_STATE_WITNESS_TOTAL_SIZE .with_label_values(&[shard_id_label.as_str()]) - .observe(signed_witness.witness_bytes.size_bytes() as f64); + .observe(witness_bytes.size_bytes() as f64); metrics::CHUNK_STATE_WITNESS_RAW_SIZE .with_label_values(&[shard_id_label.as_str()]) .observe(raw_witness_size as f64); - Ok(signed_witness) + Ok(witness_bytes) } diff --git a/chain/client/src/stateless_validation/state_witness_actor.rs b/chain/client/src/stateless_validation/state_witness_actor.rs index 8884e629c69..d3ee9986318 100644 --- a/chain/client/src/stateless_validation/state_witness_actor.rs +++ b/chain/client/src/stateless_validation/state_witness_actor.rs @@ -12,7 +12,9 @@ use near_network::state_witness::{ use near_network::types::PeerManagerAdapter; use near_o11y::{handler_debug_span, WithSpanContext}; use near_performance_metrics_macros::perf; +use near_primitives::sharding::ShardChunkHeader; use near_primitives::stateless_validation::ChunkStateWitness; +use near_primitives::types::EpochId; use near_primitives::validator_signer::ValidatorSigner; use super::state_witness_actions::StateWitnessActions; @@ -43,6 +45,8 @@ impl actix::Actor for StateWitnessActor { #[derive(actix::Message, Debug)] #[rtype(result = "()")] pub struct DistributeStateWitnessRequest { + pub epoch_id: EpochId, + pub chunk_header: ShardChunkHeader, pub state_witness: ChunkStateWitness, } diff --git a/chain/client/src/stateless_validation/state_witness_producer.rs b/chain/client/src/stateless_validation/state_witness_producer.rs index 9c47767c5ed..b718bfbced9 100644 --- a/chain/client/src/stateless_validation/state_witness_producer.rs +++ b/chain/client/src/stateless_validation/state_witness_producer.rs @@ -61,7 +61,11 @@ impl Client { ); } - self.state_witness_adapter.send(DistributeStateWitnessRequest { state_witness }); + self.state_witness_adapter.send(DistributeStateWitnessRequest { + epoch_id: epoch_id.clone(), + chunk_header, + state_witness, + }); Ok(()) } diff --git a/chain/network/src/types.rs b/chain/network/src/types.rs index b393ad9ea0a..f41afa3112f 100644 --- a/chain/network/src/types.rs +++ b/chain/network/src/types.rs @@ -259,6 +259,7 @@ pub enum NetworkRequests { TxStatus(AccountId, AccountId, CryptoHash), /// A challenge to invalidate a block. Challenge(Challenge), + /// TODO(stateless_validation): Deprecate once we send state witness in parts. /// A chunk's state witness. ChunkStateWitness(Vec, SignedEncodedChunkStateWitness), /// Acknowledgement to a chunk's state witness, sent back to the originating chunk producer. diff --git a/core/primitives-core/src/version.rs b/core/primitives-core/src/version.rs index 9437d752f96..474910be6f3 100644 --- a/core/primitives-core/src/version.rs +++ b/core/primitives-core/src/version.rs @@ -152,6 +152,8 @@ pub enum ProtocolFeature { // Stateless validation: in statelessnet, shuffle shard assignments for chunk producers every // epoch. StatelessnetShuffleShardAssignmentsForChunkProducers, + // Send state witness in encoded parts. + PartialEncodedStateWitness, } impl ProtocolFeature { @@ -218,6 +220,7 @@ impl ProtocolFeature { ProtocolFeature::SingleShardTracking => 82, ProtocolFeature::StateWitnessSizeLimit => 83, ProtocolFeature::StatelessnetShuffleShardAssignmentsForChunkProducers => 84, + ProtocolFeature::PartialEncodedStateWitness => 86, // Nightly features #[cfg(feature = "protocol_feature_fix_staking_threshold")] @@ -243,7 +246,7 @@ const STABLE_PROTOCOL_VERSION: ProtocolVersion = 67; /// Largest protocol version supported by the current binary. pub const PROTOCOL_VERSION: ProtocolVersion = if cfg!(feature = "statelessnet_protocol") { // Current StatelessNet protocol version. - 84 + 86 } else if cfg!(feature = "nightly_protocol") { // On nightly, pick big enough version to support all features. 140 diff --git a/core/primitives/src/stateless_validation.rs b/core/primitives/src/stateless_validation.rs index d47ee24b448..bc28357b415 100644 --- a/core/primitives/src/stateless_validation.rs +++ b/core/primitives/src/stateless_validation.rs @@ -19,13 +19,85 @@ use near_primitives_core::types::{AccountId, Balance, BlockHeight, ShardId}; /// This is a messy workaround until we know what to do with NEP 483. type SignatureDifferentiator = String; -// TODO(shreyan): Fill this struct #[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] -pub struct PartialEncodedStateWitness {} +pub struct PartialEncodedStateWitness { + inner: PartialEncodedStateWitnessInner, + pub signature: Signature, +} + +impl PartialEncodedStateWitness { + pub fn new( + epoch_id: EpochId, + chunk_header: ShardChunkHeader, + part_ord: usize, + part: Vec, + encoded_length: usize, + signer: &dyn ValidatorSigner, + ) -> Self { + let inner = PartialEncodedStateWitnessInner::new( + epoch_id, + chunk_header, + part_ord, + part, + encoded_length, + ); + let signature = signer.sign_partial_encoded_state_witness(&inner); + Self { inner, signature } + } + + pub fn verify(&self, public_key: &PublicKey) -> bool { + let data = borsh::to_vec(&self.inner).unwrap(); + self.signature.verify(&data, public_key) + } + + pub fn epoch_id(&self) -> &EpochId { + &self.inner.epoch_id + } + + pub fn chunk_header(&self) -> &ShardChunkHeader { + &self.inner.chunk_header + } + + pub fn part_ord(&self) -> usize { + self.inner.part_ord + } + + pub fn part(&self) -> &[u8] { + &self.inner.part + } +} + +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +pub struct PartialEncodedStateWitnessInner { + epoch_id: EpochId, + chunk_header: ShardChunkHeader, + part_ord: usize, + part: Box<[u8]>, + encoded_length: usize, + signature_differentiator: SignatureDifferentiator, +} + +impl PartialEncodedStateWitnessInner { + fn new( + epoch_id: EpochId, + chunk_header: ShardChunkHeader, + part_ord: usize, + part: Vec, + encoded_length: usize, + ) -> Self { + Self { + epoch_id, + chunk_header, + part_ord, + part: part.into_boxed_slice(), + encoded_length, + signature_differentiator: "PartialEncodedStateWitness".to_owned(), + } + } +} /// Represents bytes of encoded ChunkStateWitness. -/// For now encoding is raw borsh serialization, later we plan -/// adding compression on top of that. +/// This is the compressed version of borsh-serialized state witness. #[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] pub struct EncodedChunkStateWitness(Box<[u8]>); @@ -63,6 +135,7 @@ impl EncodedChunkStateWitness { } } +// TODO(stateless_validation): Deprecate once we send state witness in parts. #[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] pub struct SignedEncodedChunkStateWitness { /// The content of the witness. It is convenient have it as bytes in order @@ -102,10 +175,12 @@ pub struct ChunkStateWitness { /// with chunk_header.prev_block_hash(). /// This is needed to validate signature when the previous block is not yet /// available on the validator side (aka orphan state witness). + /// TODO(stateless_validation): Deprecate once we send state witness in parts. pub epoch_id: EpochId, /// The chunk header that this witness is for. While this is not needed /// to apply the state transition, it is needed for a chunk validator to /// produce a chunk endorsement while knowing what they are endorsing. + /// TODO(stateless_validation): Deprecate once we send state witness in parts. pub chunk_header: ShardChunkHeader, /// The base state and post-state-root of the main transition where we /// apply transactions and receipts. Corresponds to the state transition @@ -165,6 +240,7 @@ pub struct ChunkStateWitness { /// accounts have appropriate balances, access keys, nonces, etc. pub new_transactions: Vec, pub new_transactions_validation_state: PartialState, + // TODO(stateless_validation): Deprecate once we send state witness in parts. signature_differentiator: SignatureDifferentiator, } diff --git a/core/primitives/src/validator_signer.rs b/core/primitives/src/validator_signer.rs index d876bbe84cd..69fd3e41b43 100644 --- a/core/primitives/src/validator_signer.rs +++ b/core/primitives/src/validator_signer.rs @@ -8,7 +8,9 @@ use crate::challenge::ChallengeBody; use crate::hash::CryptoHash; use crate::network::{AnnounceAccount, PeerId}; use crate::sharding::ChunkHash; -use crate::stateless_validation::{ChunkEndorsementInner, EncodedChunkStateWitness}; +use crate::stateless_validation::{ + ChunkEndorsementInner, EncodedChunkStateWitness, PartialEncodedStateWitnessInner, +}; use crate::telemetry::TelemetryInfo; use crate::types::{AccountId, BlockHeight, EpochId}; @@ -37,12 +39,18 @@ pub trait ValidatorSigner: Sync + Send { /// Signs approval of given parent hash and reference hash. fn sign_approval(&self, inner: &ApprovalInner, target_height: BlockHeight) -> Signature; - /// Signs approval of the given chunk. + /// Signs chunk endorsement to be sent to block producer. fn sign_chunk_endorsement(&self, inner: &ChunkEndorsementInner) -> Signature; - /// Signs approval of the given chunk. + /// Signs chunk state witness to be sent to all validators. fn sign_chunk_state_witness(&self, witness_bytes: &EncodedChunkStateWitness) -> Signature; + /// Signs partial encoded state witness to be sent and forwarded to all validators. + fn sign_partial_encoded_state_witness( + &self, + part: &PartialEncodedStateWitnessInner, + ) -> Signature; + /// Signs challenge body. fn sign_challenge(&self, challenge_body: &ChallengeBody) -> (CryptoHash, Signature); @@ -123,6 +131,13 @@ impl ValidatorSigner for EmptyValidatorSigner { Signature::default() } + fn sign_partial_encoded_state_witness( + &self, + _part: &PartialEncodedStateWitnessInner, + ) -> Signature { + Signature::default() + } + fn sign_challenge(&self, challenge_body: &ChallengeBody) -> (CryptoHash, Signature) { (CryptoHash::hash_borsh(challenge_body), Signature::default()) } @@ -222,6 +237,13 @@ impl ValidatorSigner for InMemoryValidatorSigner { self.signer.sign(witness_bytes.as_slice()) } + fn sign_partial_encoded_state_witness( + &self, + part: &PartialEncodedStateWitnessInner, + ) -> Signature { + self.signer.sign(&borsh::to_vec(part).unwrap()) + } + fn sign_challenge(&self, challenge_body: &ChallengeBody) -> (CryptoHash, Signature) { let hash = CryptoHash::hash_borsh(challenge_body); let signature = self.signer.sign(hash.as_ref()); From 29c67eddd41b07ef6eabe9c23327e02e0ed05e2a Mon Sep 17 00:00:00 2001 From: Shreyan Gupta Date: Thu, 18 Apr 2024 21:20:28 -0700 Subject: [PATCH 2/3] fix --- .../src/stateless_validation/state_witness_actions.rs | 11 +++-------- core/primitives-core/src/version.rs | 5 +---- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/chain/client/src/stateless_validation/state_witness_actions.rs b/chain/client/src/stateless_validation/state_witness_actions.rs index 2054bad3eef..78b715e3d89 100644 --- a/chain/client/src/stateless_validation/state_witness_actions.rs +++ b/chain/client/src/stateless_validation/state_witness_actions.rs @@ -7,7 +7,6 @@ use near_async::time::Clock; use near_chain::Error; use near_epoch_manager::EpochManagerAdapter; use near_network::types::{NetworkRequests, PeerManagerAdapter, PeerManagerMessageRequest}; -use near_primitives::checked_feature; use near_primitives::reed_solomon::ReedSolomonWrapper; use near_primitives::sharding::ShardChunkHeader; use near_primitives::stateless_validation::{ @@ -84,13 +83,8 @@ impl StateWitnessActions { chunk_validators.len(), ); - let protocol_version = self.epoch_manager.get_epoch_protocol_version(&epoch_id)?; - if !checked_feature!("stable", PartialEncodedStateWitness, protocol_version) { - // TODO(stateless_validation): Deprecate once we send state witness in parts. - self.send_state_witness(witness_bytes, chunk_validators); - } else { - self.send_state_witness_parts(epoch_id, chunk_header, witness_bytes, chunk_validators)?; - } + // TODO(stateless_validation): Replace with call to send_state_witness_parts after full implementation + self.send_state_witness(witness_bytes, chunk_validators); Ok(()) } @@ -119,6 +113,7 @@ impl StateWitnessActions { // Break the state witness into parts and send each part to the corresponding chunk validator owner. // The chunk validator owner will then forward the part to all other chunk validators. // Each chunk validator would collect the parts and reconstruct the state witness. + #[allow(unused)] fn send_state_witness_parts( &mut self, epoch_id: EpochId, diff --git a/core/primitives-core/src/version.rs b/core/primitives-core/src/version.rs index 474910be6f3..9437d752f96 100644 --- a/core/primitives-core/src/version.rs +++ b/core/primitives-core/src/version.rs @@ -152,8 +152,6 @@ pub enum ProtocolFeature { // Stateless validation: in statelessnet, shuffle shard assignments for chunk producers every // epoch. StatelessnetShuffleShardAssignmentsForChunkProducers, - // Send state witness in encoded parts. - PartialEncodedStateWitness, } impl ProtocolFeature { @@ -220,7 +218,6 @@ impl ProtocolFeature { ProtocolFeature::SingleShardTracking => 82, ProtocolFeature::StateWitnessSizeLimit => 83, ProtocolFeature::StatelessnetShuffleShardAssignmentsForChunkProducers => 84, - ProtocolFeature::PartialEncodedStateWitness => 86, // Nightly features #[cfg(feature = "protocol_feature_fix_staking_threshold")] @@ -246,7 +243,7 @@ const STABLE_PROTOCOL_VERSION: ProtocolVersion = 67; /// Largest protocol version supported by the current binary. pub const PROTOCOL_VERSION: ProtocolVersion = if cfg!(feature = "statelessnet_protocol") { // Current StatelessNet protocol version. - 86 + 84 } else if cfg!(feature = "nightly_protocol") { // On nightly, pick big enough version to support all features. 140 From 2a6424963a09a1d7034875811ba9855ee8c404cc Mon Sep 17 00:00:00 2001 From: Shreyan Gupta Date: Thu, 18 Apr 2024 22:27:35 -0700 Subject: [PATCH 3/3] fix --- chain/network/src/peer/testonly.rs | 1 + chain/network/src/peer_manager/testonly.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/chain/network/src/peer/testonly.rs b/chain/network/src/peer/testonly.rs index 78f24c18fd8..b3bbaae6855 100644 --- a/chain/network/src/peer/testonly.rs +++ b/chain/network/src/peer/testonly.rs @@ -41,6 +41,7 @@ impl PeerConfig { } #[derive(Debug, Clone, PartialEq, Eq)] +#[allow(clippy::large_enum_variant)] pub(crate) enum Event { ShardsManager(ShardsManagerRequestFromNetwork), Client(ClientSenderForNetworkInput), diff --git a/chain/network/src/peer_manager/testonly.rs b/chain/network/src/peer_manager/testonly.rs index e0f9b85821f..17a0e26cb86 100644 --- a/chain/network/src/peer_manager/testonly.rs +++ b/chain/network/src/peer_manager/testonly.rs @@ -68,6 +68,7 @@ impl actix::Handler for PeerManagerActor { } #[derive(Debug, PartialEq, Eq, Clone)] +#[allow(clippy::large_enum_variant)] pub enum Event { ShardsManager(ShardsManagerRequestFromNetwork), Client(ClientSenderForNetworkInput),