diff --git a/chain/chain/src/test_utils/kv_runtime.rs b/chain/chain/src/test_utils/kv_runtime.rs index 99e391f3961..1f97a849816 100644 --- a/chain/chain/src/test_utils/kv_runtime.rs +++ b/chain/chain/src/test_utils/kv_runtime.rs @@ -32,7 +32,7 @@ use near_primitives::shard_layout; use near_primitives::shard_layout::{ShardLayout, ShardUId}; use near_primitives::sharding::{ChunkHash, ShardChunkHeader}; use near_primitives::state_part::PartId; -use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsement; +use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsementV1; use near_primitives::stateless_validation::partial_witness::PartialEncodedStateWitness; use near_primitives::stateless_validation::validator_assignment::ChunkValidatorAssignments; use near_primitives::transaction::{ @@ -945,7 +945,7 @@ impl EpochManagerAdapter for MockEpochManager { fn verify_chunk_endorsement( &self, _chunk_header: &ShardChunkHeader, - _endorsement: &ChunkEndorsement, + _endorsement: &ChunkEndorsementV1, ) -> Result { Ok(true) } diff --git a/chain/chain/src/tests/simple_chain.rs b/chain/chain/src/tests/simple_chain.rs index 5998b71408a..f7a52122e7a 100644 --- a/chain/chain/src/tests/simple_chain.rs +++ b/chain/chain/src/tests/simple_chain.rs @@ -32,7 +32,7 @@ fn build_chain() { // cargo insta test --accept -p near-chain --features nightly -- tests::simple_chain::build_chain let hash = chain.head().unwrap().last_block_hash; if cfg!(feature = "nightly") { - insta::assert_snapshot!(hash, @"C3zeKRZubVungxfrSdq379TSCYnuz2YzjEkcJTdm3pU4"); + insta::assert_snapshot!(hash, @"H9qfaTFJ7jFMEmJX9eYQ3kJQ6vwATAhidfbjwa9PvCPK"); } else { insta::assert_snapshot!(hash, @"EeGa9BFTyrPoM56iZBteXZfhq86g4k1tjMCPprqYyfKF"); } @@ -50,7 +50,7 @@ fn build_chain() { let hash = chain.head().unwrap().last_block_hash; if cfg!(feature = "nightly") { - insta::assert_snapshot!(hash, @"EjLaoHRiAdRp2NcDqwbMcAYYxGfcv5R7GuYUNfRpaJvB"); + insta::assert_snapshot!(hash, @"HPRdNbp8dJL2JA5bRSmLg6GJpGXx6xmw472vVAWLpXhi"); } else { insta::assert_snapshot!(hash, @"Em7E1W5xPMTToyiGbRAES2iAKJQDsZ5m8ymvy4S7adxu"); } diff --git a/chain/client/src/stateless_validation/chunk_endorsement_tracker.rs b/chain/client/src/stateless_validation/chunk_endorsement_tracker.rs index 59f1920c958..70e4dd827dc 100644 --- a/chain/client/src/stateless_validation/chunk_endorsement_tracker.rs +++ b/chain/client/src/stateless_validation/chunk_endorsement_tracker.rs @@ -1,6 +1,8 @@ use lru::LruCache; use near_chain::ChainStoreAccess; -use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsement; +use near_primitives::stateless_validation::chunk_endorsement::{ + ChunkEndorsement, ChunkEndorsementV1, +}; use near_primitives::stateless_validation::validator_assignment::EndorsementStats; use std::collections::HashMap; use std::num::NonZeroUsize; @@ -45,36 +47,51 @@ struct ChunkEndorsementTrackerInner { /// This is keyed on chunk_hash and account_id of validator to avoid duplicates. /// Chunk endorsements would later be used as a part of block production. chunk_endorsements: - LruCache)>, + LruCache)>, /// We store chunk endorsements to be processed later because we did not have /// chunks ready at the time we received that endorsements from validators. /// This is keyed on chunk_hash and account_id of validator to avoid duplicates. - pending_chunk_endorsements: LruCache>, + pending_chunk_endorsements: LruCache>, } impl Client { pub fn process_chunk_endorsement( &mut self, endorsement: ChunkEndorsement, + ) -> Result<(), Error> { + // TODO(ChunkEndorsementV2): Remove chunk_header once tracker_v1 is deprecated + let chunk_header = + match self.chain.chain_store().get_partial_chunk(endorsement.chunk_hash()) { + Ok(chunk) => Some(chunk.cloned_header()), + Err(Error::ChunkMissing(_)) => None, + Err(error) => return Err(error), + }; + match endorsement { + ChunkEndorsement::V1(endorsement) => { + self.chunk_endorsement_tracker.process_chunk_endorsement(endorsement, chunk_header) + } + } + } +} + +impl ChunkEndorsementTracker { + pub fn process_chunk_endorsement( + &self, + endorsement: ChunkEndorsementV1, + chunk_header: Option, ) -> Result<(), Error> { // We need the chunk header in order to process the chunk endorsement. // If we don't have the header, then queue it up for when we do have the header. // We must use the partial chunk (as opposed to the full chunk) in order to get // the chunk header, because we may not be tracking that shard. - match self.chain.chain_store().get_partial_chunk(endorsement.chunk_hash()) { - Ok(chunk) => self - .chunk_endorsement_tracker - .process_chunk_endorsement(&chunk.cloned_header(), endorsement), - Err(Error::ChunkMissing(_)) => { - tracing::debug!(target: "client", ?endorsement, "Endorsement arrived before chunk."); - self.chunk_endorsement_tracker.add_chunk_endorsement_to_pending_cache(endorsement) + match chunk_header { + Some(chunk_header) => { + self.process_chunk_endorsement_with_chunk_header(&chunk_header, endorsement) } - Err(error) => return Err(error), + None => self.add_chunk_endorsement_to_pending_cache(endorsement), } } -} -impl ChunkEndorsementTracker { pub fn new(epoch_manager: Arc) -> Self { Self { epoch_manager: epoch_manager.clone(), @@ -100,7 +117,7 @@ impl ChunkEndorsementTracker { /// Add the chunk endorsement to a cache of pending chunk endorsements (if not yet there). pub(crate) fn add_chunk_endorsement_to_pending_cache( &self, - endorsement: ChunkEndorsement, + endorsement: ChunkEndorsementV1, ) -> Result<(), Error> { self.inner.lock().unwrap().process_chunk_endorsement_impl(endorsement, None, false) } @@ -108,10 +125,10 @@ impl ChunkEndorsementTracker { /// Function to process an incoming chunk endorsement from chunk validators. /// We first verify the chunk endorsement and then store it in a cache. /// We would later include the endorsements in the block production. - pub(crate) fn process_chunk_endorsement( + fn process_chunk_endorsement_with_chunk_header( &self, chunk_header: &ShardChunkHeader, - endorsement: ChunkEndorsement, + endorsement: ChunkEndorsementV1, ) -> Result<(), Error> { let _span = tracing::debug_span!(target: "client", "process_chunk_endorsement", chunk_hash=?chunk_header.chunk_hash(), shard_id=chunk_header.shard_id()).entered(); // Validate the endorsement before locking the mutex to improve performance. @@ -164,7 +181,7 @@ impl ChunkEndorsementTrackerInner { /// Otherwise, we store the endorsement in a separate cache of endorsements to be processed when the chunk is ready. fn process_chunk_endorsement_impl( &mut self, - endorsement: ChunkEndorsement, + endorsement: ChunkEndorsementV1, chunk_header: Option<&ShardChunkHeader>, already_validated: bool, ) -> Result<(), Error> { diff --git a/chain/client/src/stateless_validation/chunk_validator/mod.rs b/chain/client/src/stateless_validation/chunk_validator/mod.rs index f2cbb181752..cd1a9e61172 100644 --- a/chain/client/src/stateless_validation/chunk_validator/mod.rs +++ b/chain/client/src/stateless_validation/chunk_validator/mod.rs @@ -16,7 +16,9 @@ use near_epoch_manager::EpochManagerAdapter; use near_network::types::{NetworkRequests, PeerManagerMessageRequest}; use near_o11y::log_assert; use near_primitives::sharding::ShardChunkHeader; -use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsement; +use near_primitives::stateless_validation::chunk_endorsement::{ + ChunkEndorsement, ChunkEndorsementV1, +}; use near_primitives::stateless_validation::state_witness::{ ChunkStateWitness, ChunkStateWitnessAck, ChunkStateWitnessSize, }; @@ -227,12 +229,12 @@ pub(crate) fn send_chunk_endorsement_to_block_producers( "send_chunk_endorsement", ); - let endorsement = ChunkEndorsement::new(chunk_header.chunk_hash(), signer); + let endorsement = ChunkEndorsementV1::new(chunk_header.chunk_hash(), signer); for block_producer in block_producers { if signer.validator_id() == &block_producer { // Our own endorsements are not always valid (see issue #11750). if let Err(err) = chunk_endorsement_tracker - .process_chunk_endorsement(chunk_header, endorsement.clone()) + .process_chunk_endorsement(endorsement.clone(), Some(chunk_header.clone())) { tracing::warn!( target: "client", @@ -242,7 +244,10 @@ pub(crate) fn send_chunk_endorsement_to_block_producers( } } else { network_sender.send(PeerManagerMessageRequest::NetworkRequests( - NetworkRequests::ChunkEndorsement(block_producer, endorsement.clone()), + NetworkRequests::ChunkEndorsement( + block_producer, + ChunkEndorsement::V1(endorsement.clone()), + ), )); } } diff --git a/chain/client/src/test_utils/client.rs b/chain/client/src/test_utils/client.rs index 0576cd6cad6..3eff025690b 100644 --- a/chain/client/src/test_utils/client.rs +++ b/chain/client/src/test_utils/client.rs @@ -21,7 +21,7 @@ use near_primitives::block::Block; use near_primitives::hash::CryptoHash; use near_primitives::merkle::{merklize, PartialMerkleTree}; use near_primitives::sharding::{EncodedShardChunk, ShardChunk}; -use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsement; +use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsementV1; use near_primitives::transaction::SignedTransaction; use near_primitives::types::{BlockHeight, ShardId}; use near_primitives::utils::MaybeValidated; @@ -249,7 +249,7 @@ pub fn create_chunk( let mut block_merkle_tree = PartialMerkleTree::clone(&block_merkle_tree); let signer = client.validator_signer.get().unwrap(); - let endorsement = ChunkEndorsement::new(chunk.cloned_header().chunk_hash(), signer.as_ref()); + let endorsement = ChunkEndorsementV1::new(chunk.cloned_header().chunk_hash(), signer.as_ref()); block_merkle_tree.insert(*last_block.hash()); let block = Block::produce( PROTOCOL_VERSION, diff --git a/chain/client/src/test_utils/test_env.rs b/chain/client/src/test_utils/test_env.rs index b856a6d0caa..a3504fb5052 100644 --- a/chain/client/src/test_utils/test_env.rs +++ b/chain/client/src/test_utils/test_env.rs @@ -27,7 +27,9 @@ use near_primitives::epoch_manager::RngSeed; use near_primitives::errors::InvalidTxError; use near_primitives::hash::CryptoHash; use near_primitives::sharding::{ChunkHash, PartialEncodedChunk}; -use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsement; +use near_primitives::stateless_validation::chunk_endorsement::{ + ChunkEndorsement, ChunkEndorsementV1, +}; use near_primitives::stateless_validation::state_witness::ChunkStateWitness; use near_primitives::test_utils::create_test_signer; use near_primitives::transaction::{Action, FunctionCallAction, SignedTransaction}; @@ -432,11 +434,13 @@ impl TestEnv { /// Wait until an endorsement for `chunk_hash` appears in the network messages send by /// the Client with index `client_idx`. Times out after CHUNK_ENDORSEMENTS_TIMEOUT. /// Doesn't process or consume the message, it just waits until the message appears on the network_adapter. + /// TODO(ChunkEndorsementV2): This function is only used by orphan_chunk_state_witnesses test. + /// Can remove once we shift to ChunkEndorsementV2. pub fn wait_for_chunk_endorsement( &mut self, client_idx: usize, chunk_hash: &ChunkHash, - ) -> Result { + ) -> Result { let start_time = Instant::now(); let network_adapter = self.network_adapters[client_idx].clone(); loop { @@ -445,8 +449,13 @@ impl TestEnv { match &request { PeerManagerMessageRequest::NetworkRequests( NetworkRequests::ChunkEndorsement(_receiver_account_id, endorsement), - ) if endorsement.chunk_hash() == chunk_hash => { - endorsement_opt = Some(endorsement.clone()); + ) => { + let endorsement = match endorsement { + ChunkEndorsement::V1(endorsement) => endorsement, + }; + if endorsement.chunk_hash() == chunk_hash { + endorsement_opt = Some(endorsement.clone()); + } } _ => {} }; diff --git a/chain/epoch-manager/src/adapter.rs b/chain/epoch-manager/src/adapter.rs index 566fbe1821d..f04d925e527 100644 --- a/chain/epoch-manager/src/adapter.rs +++ b/chain/epoch-manager/src/adapter.rs @@ -13,7 +13,7 @@ use near_primitives::errors::EpochError; use near_primitives::hash::CryptoHash; use near_primitives::shard_layout::{account_id_to_shard_id, ShardLayout, ShardLayoutError}; use near_primitives::sharding::{ChunkHash, ShardChunkHeader}; -use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsement; +use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsementV1; use near_primitives::stateless_validation::partial_witness::PartialEncodedStateWitness; use near_primitives::stateless_validation::validator_assignment::ChunkValidatorAssignments; use near_primitives::types::validator_stake::ValidatorStake; @@ -418,7 +418,7 @@ pub trait EpochManagerAdapter: Send + Sync { fn verify_chunk_endorsement( &self, chunk_header: &ShardChunkHeader, - endorsement: &ChunkEndorsement, + endorsement: &ChunkEndorsementV1, ) -> Result; fn verify_partial_witness_signature( @@ -1049,7 +1049,7 @@ impl EpochManagerAdapter for EpochManagerHandle { fn verify_chunk_endorsement( &self, chunk_header: &ShardChunkHeader, - endorsement: &ChunkEndorsement, + endorsement: &ChunkEndorsementV1, ) -> Result { if &chunk_header.chunk_hash() != endorsement.chunk_hash() { return Err(Error::InvalidChunkEndorsement); diff --git a/chain/epoch-manager/src/tests/mod.rs b/chain/epoch-manager/src/tests/mod.rs index 4c3ea5b617b..5e369a3e11c 100644 --- a/chain/epoch-manager/src/tests/mod.rs +++ b/chain/epoch-manager/src/tests/mod.rs @@ -19,7 +19,7 @@ use near_primitives::epoch_manager::EpochConfig; use near_primitives::hash::hash; use near_primitives::shard_layout::ShardLayout; use near_primitives::sharding::{ShardChunkHeader, ShardChunkHeaderV3}; -use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsement; +use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsementV1; use near_primitives::stateless_validation::partial_witness::PartialEncodedStateWitness; use near_primitives::types::ValidatorKickoutReason::{ NotEnoughBlocks, NotEnoughChunkEndorsements, NotEnoughChunks, @@ -2818,7 +2818,7 @@ fn test_verify_chunk_endorsements() { let chunk_header = test_chunk_header(&h, signer.as_ref()); // check chunk endorsement validity - let mut chunk_endorsement = ChunkEndorsement::new(chunk_header.chunk_hash(), signer.as_ref()); + let mut chunk_endorsement = ChunkEndorsementV1::new(chunk_header.chunk_hash(), signer.as_ref()); assert!(epoch_manager.verify_chunk_endorsement(&chunk_header, &chunk_endorsement).unwrap()); // check invalid chunk endorsement signature @@ -2826,7 +2826,7 @@ fn test_verify_chunk_endorsements() { assert!(!epoch_manager.verify_chunk_endorsement(&chunk_header, &chunk_endorsement).unwrap()); // check chunk endorsement invalidity when chunk header and chunk endorsement don't match - let chunk_endorsement = ChunkEndorsement::new(h[3].into(), signer.as_ref()); + let chunk_endorsement = ChunkEndorsementV1::new(h[3].into(), signer.as_ref()); let err = epoch_manager.verify_chunk_endorsement(&chunk_header, &chunk_endorsement).unwrap_err(); match err { @@ -2836,7 +2836,7 @@ fn test_verify_chunk_endorsements() { // check chunk endorsement invalidity when signer is not chunk validator let bad_signer = Arc::new(create_test_signer("test2")); - let chunk_endorsement = ChunkEndorsement::new(chunk_header.chunk_hash(), bad_signer.as_ref()); + let chunk_endorsement = ChunkEndorsementV1::new(chunk_header.chunk_hash(), bad_signer.as_ref()); let err = epoch_manager.verify_chunk_endorsement(&chunk_header, &chunk_endorsement).unwrap_err(); match err { diff --git a/chain/network/src/network_protocol/mod.rs b/chain/network/src/network_protocol/mod.rs index a97cd628982..86d59709bde 100644 --- a/chain/network/src/network_protocol/mod.rs +++ b/chain/network/src/network_protocol/mod.rs @@ -8,6 +8,7 @@ mod proto_conv; mod state_sync; pub use edge::*; use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsement; +use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsementV1; use near_primitives::stateless_validation::partial_witness::PartialEncodedStateWitness; use near_primitives::stateless_validation::state_witness::ChunkStateWitnessAck; pub use peer::*; @@ -531,10 +532,12 @@ pub enum RoutedMessageBody { _UnusedVersionedStateResponse, PartialEncodedChunkForward(PartialEncodedChunkForwardMsg), _UnusedChunkStateWitness, - ChunkEndorsement(ChunkEndorsement), + /// TODO(ChunkEndorsementV2): Deprecate once we move to VersionedChunkEndorsement + ChunkEndorsement(ChunkEndorsementV1), ChunkStateWitnessAck(ChunkStateWitnessAck), PartialEncodedStateWitness(PartialEncodedStateWitness), PartialEncodedStateWitnessForward(PartialEncodedStateWitness), + VersionedChunkEndorsement(ChunkEndorsement), } impl RoutedMessageBody { @@ -607,6 +610,9 @@ impl fmt::Debug for RoutedMessageBody { RoutedMessageBody::PartialEncodedStateWitnessForward(_) => { write!(f, "PartialEncodedStateWitnessForward") } + RoutedMessageBody::VersionedChunkEndorsement(_) => { + write!(f, "VersionedChunkEndorsement") + } } } } diff --git a/chain/network/src/peer/peer_actor.rs b/chain/network/src/peer/peer_actor.rs index b327583502f..f31e58f1c4b 100644 --- a/chain/network/src/peer/peer_actor.rs +++ b/chain/network/src/peer/peer_actor.rs @@ -45,6 +45,7 @@ use near_o11y::{handler_debug_span, log_assert, WithSpanContext}; use near_performance_metrics_macros::perf; use near_primitives::hash::CryptoHash; use near_primitives::network::{AnnounceAccount, PeerId}; +use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsement; use near_primitives::types::EpochId; use near_primitives::utils::DisplayOption; use near_primitives::version::{ @@ -1028,6 +1029,7 @@ impl PeerActor { None } RoutedMessageBody::ChunkEndorsement(endorsement) => { + let endorsement = ChunkEndorsement::V1(endorsement); network_state.client.send_async(ChunkEndorsementMessage(endorsement)).await.ok(); None } @@ -1043,6 +1045,10 @@ impl PeerActor { .send(PartialEncodedStateWitnessForwardMessage(witness)); None } + RoutedMessageBody::VersionedChunkEndorsement(endorsement) => { + network_state.client.send_async(ChunkEndorsementMessage(endorsement)).await.ok(); + None + } body => { tracing::error!(target: "network", "Peer received unexpected message type: {:?}", body); None diff --git a/chain/network/src/peer_manager/peer_manager_actor.rs b/chain/network/src/peer_manager/peer_manager_actor.rs index fed881aa6ef..aa22c236770 100644 --- a/chain/network/src/peer_manager/peer_manager_actor.rs +++ b/chain/network/src/peer_manager/peer_manager_actor.rs @@ -30,6 +30,7 @@ use near_o11y::{handler_debug_span, handler_trace_span, WithSpanContext}; use near_performance_metrics_macros::perf; use near_primitives::block::GenesisId; use near_primitives::network::{AnnounceAccount, PeerId}; +use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsement; use near_primitives::views::{ ConnectionInfoView, EdgeView, KnownPeerStateView, NetworkGraphView, PeerStoreView, RecentOutboundConnectionsView, SnapshotHostInfoView, SnapshotHostsView, @@ -980,11 +981,12 @@ impl PeerManagerActor { NetworkResponses::NoResponse } NetworkRequests::ChunkEndorsement(target, endorsement) => { - self.state.send_message_to_account( - &self.clock, - &target, - RoutedMessageBody::ChunkEndorsement(endorsement), - ); + let msg = match endorsement { + ChunkEndorsement::V1(endorsement) => { + RoutedMessageBody::ChunkEndorsement(endorsement) + } + }; + self.state.send_message_to_account(&self.clock, &target, msg); NetworkResponses::NoResponse } NetworkRequests::PartialEncodedStateWitness(validator_witness_tuple) => { diff --git a/chain/network/src/rate_limits/messages_limits.rs b/chain/network/src/rate_limits/messages_limits.rs index 4c68f38133d..c02eb954b89 100644 --- a/chain/network/src/rate_limits/messages_limits.rs +++ b/chain/network/src/rate_limits/messages_limits.rs @@ -217,6 +217,7 @@ fn get_key_and_token_cost(message: &PeerMessage) -> Option<(RateLimitedPeerMessa RoutedMessageBody::PartialEncodedStateWitnessForward(_) => { Some((PartialEncodedStateWitnessForward, 1)) } + RoutedMessageBody::VersionedChunkEndorsement(_) => Some((ChunkEndorsement, 1)), RoutedMessageBody::Ping(_) | RoutedMessageBody::Pong(_) | RoutedMessageBody::_UnusedChunkStateWitness diff --git a/core/primitives-core/src/version.rs b/core/primitives-core/src/version.rs index 1acebf686d3..c4b360a51b7 100644 --- a/core/primitives-core/src/version.rs +++ b/core/primitives-core/src/version.rs @@ -157,6 +157,9 @@ pub enum ProtocolFeature { CongestionControl, /// Remove account with long storage key. RemoveAccountWithLongStorageKey, + /// Change the structure of ChunkEndorsement to have (shard_id, epoch_id, height_created) + /// instead of chunk_hash + ChunkEndorsementV2, } impl ProtocolFeature { @@ -228,6 +231,7 @@ impl ProtocolFeature { // TODO(#11201): When stabilizing this feature in mainnet, also remove the temporary code // that always enables this for mocknet (see config_mocknet function). ProtocolFeature::ShuffleShardAssignments => 143, + ProtocolFeature::ChunkEndorsementV2 => 144, } } @@ -248,7 +252,7 @@ pub const PROTOCOL_VERSION: ProtocolVersion = if cfg!(feature = "statelessnet_pr 82 } else if cfg!(feature = "nightly_protocol") { // On nightly, pick big enough version to support all features. - 143 + 144 } else { // Enable all stable features. STABLE_PROTOCOL_VERSION diff --git a/core/primitives/src/stateless_validation/chunk_endorsement.rs b/core/primitives/src/stateless_validation/chunk_endorsement.rs index 949f85f8128..59402c4a865 100644 --- a/core/primitives/src/stateless_validation/chunk_endorsement.rs +++ b/core/primitives/src/stateless_validation/chunk_endorsement.rs @@ -11,27 +11,25 @@ use super::SignatureDifferentiator; /// The endorsement of a chunk by a chunk validator. By providing this, a /// chunk validator has verified that the chunk state witness is correct. #[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] -pub struct ChunkEndorsement { - inner: ChunkEndorsementInner, - pub account_id: AccountId, - pub signature: Signature, +pub enum ChunkEndorsement { + V1(ChunkEndorsementV1), } impl ChunkEndorsement { pub fn new(chunk_hash: ChunkHash, signer: &ValidatorSigner) -> ChunkEndorsement { - let inner = ChunkEndorsementInner::new(chunk_hash); - let account_id = signer.validator_id().clone(); - let signature = signer.sign_chunk_endorsement(&inner); - Self { inner, account_id, signature } + ChunkEndorsement::V1(ChunkEndorsementV1::new(chunk_hash, signer)) } - pub fn verify(&self, public_key: &PublicKey) -> bool { - let data = borsh::to_vec(&self.inner).unwrap(); - self.signature.verify(&data, public_key) + pub fn chunk_hash(&self) -> &ChunkHash { + match self { + ChunkEndorsement::V1(endorsement) => endorsement.chunk_hash(), + } } - pub fn chunk_hash(&self) -> &ChunkHash { - &self.inner.chunk_hash + pub fn signature(&self) -> Signature { + match self { + ChunkEndorsement::V1(endorsement) => endorsement.signature.clone(), + } } pub fn validate_signature( @@ -45,6 +43,31 @@ impl ChunkEndorsement { } } +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +pub struct ChunkEndorsementV1 { + inner: ChunkEndorsementInner, + pub account_id: AccountId, + pub signature: Signature, +} + +impl ChunkEndorsementV1 { + pub fn new(chunk_hash: ChunkHash, signer: &ValidatorSigner) -> ChunkEndorsementV1 { + let inner = ChunkEndorsementInner::new(chunk_hash); + let account_id = signer.validator_id().clone(); + let signature = signer.sign_chunk_endorsement(&inner); + ChunkEndorsementV1 { inner, account_id, 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 chunk_hash(&self) -> &ChunkHash { + &self.inner.chunk_hash + } +} + /// This is the part of the chunk endorsement that is actually being signed. #[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] pub struct ChunkEndorsementInner { diff --git a/integration-tests/src/tests/client/challenges.rs b/integration-tests/src/tests/client/challenges.rs index 8ac0083f48c..d552dadb0fa 100644 --- a/integration-tests/src/tests/client/challenges.rs +++ b/integration-tests/src/tests/client/challenges.rs @@ -18,7 +18,7 @@ use near_primitives::merkle::PartialMerkleTree; use near_primitives::num_rational::Ratio; use near_primitives::shard_layout::ShardUId; use near_primitives::sharding::EncodedShardChunk; -use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsement; +use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsementV1; use near_primitives::test_utils::create_test_signer; use near_primitives::transaction::SignedTransaction; use near_primitives::types::chunk_extra::ChunkExtra; @@ -416,7 +416,7 @@ fn test_verify_chunk_invalid_state_challenge() { let signer = client.validator_signer.get().unwrap(); let endorsement = - ChunkEndorsement::new(invalid_chunk.cloned_header().chunk_hash(), signer.as_ref()); + ChunkEndorsementV1::new(invalid_chunk.cloned_header().chunk_hash(), signer.as_ref()); let block = Block::produce( PROTOCOL_VERSION, PROTOCOL_VERSION, diff --git a/integration-tests/src/tests/client/features/orphan_chunk_state_witness.rs b/integration-tests/src/tests/client/features/orphan_chunk_state_witness.rs index 59648528eac..7cee652b717 100644 --- a/integration-tests/src/tests/client/features/orphan_chunk_state_witness.rs +++ b/integration-tests/src/tests/client/features/orphan_chunk_state_witness.rs @@ -18,8 +18,6 @@ use near_primitives::stateless_validation::state_witness::{ ChunkStateWitness, ChunkStateWitnessSize, }; use near_primitives::types::AccountId; -use near_primitives_core::checked_feature; -use near_primitives_core::version::PROTOCOL_VERSION; use nearcore::test_utils::TestEnvNightshadeSetupExt; struct OrphanWitnessTestEnv { @@ -207,11 +205,6 @@ fn setup_orphan_witness_test() -> OrphanWitnessTestEnv { fn test_orphan_witness_valid() { init_integration_logger(); - if !checked_feature!("stable", StatelessValidation, PROTOCOL_VERSION) { - println!("Test not applicable without StatelessValidation enabled"); - return; - } - let OrphanWitnessTestEnv { mut env, block1, @@ -246,11 +239,6 @@ fn test_orphan_witness_valid() { fn test_orphan_witness_too_large() { init_integration_logger(); - if !checked_feature!("stable", StatelessValidation, PROTOCOL_VERSION) { - println!("Test not applicable without StatelessValidation enabled"); - return; - } - let OrphanWitnessTestEnv { mut env, witness, excluded_validator, .. } = setup_orphan_witness_test(); @@ -270,11 +258,6 @@ fn test_orphan_witness_too_large() { fn test_orphan_witness_far_from_head() { init_integration_logger(); - if !checked_feature!("stable", StatelessValidation, PROTOCOL_VERSION) { - println!("Test not applicable without StatelessValidation enabled"); - return; - } - let OrphanWitnessTestEnv { mut env, mut witness, block1, excluded_validator, .. } = setup_orphan_witness_test(); @@ -303,11 +286,6 @@ fn test_orphan_witness_far_from_head() { fn test_orphan_witness_not_fully_validated() { init_integration_logger(); - if !checked_feature!("stable", StatelessValidation, PROTOCOL_VERSION) { - println!("Test not applicable without StatelessValidation enabled"); - return; - } - let OrphanWitnessTestEnv { mut env, mut witness, excluded_validator, .. } = setup_orphan_witness_test(); diff --git a/integration-tests/src/tests/client/process_blocks.rs b/integration-tests/src/tests/client/process_blocks.rs index 72a806f9c11..de41e1843db 100644 --- a/integration-tests/src/tests/client/process_blocks.rs +++ b/integration-tests/src/tests/client/process_blocks.rs @@ -48,7 +48,7 @@ use near_primitives::shard_layout::{get_block_shard_uid, ShardUId}; use near_primitives::sharding::{ShardChunkHeader, ShardChunkHeaderInner, ShardChunkHeaderV3}; use near_primitives::state_part::PartId; use near_primitives::state_sync::StatePartKey; -use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsement; +use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsementV1; use near_primitives::test_utils::create_test_signer; use near_primitives::test_utils::TestBlockBuilder; use near_primitives::transaction::{ @@ -2274,7 +2274,7 @@ fn test_validate_chunk_extra() { block.mut_header().get_mut().inner_rest.chunk_mask = vec![true]; block.mut_header().get_mut().inner_lite.prev_outcome_root = Block::compute_outcome_root(block.chunks().iter()); - let endorsement = ChunkEndorsement::new(chunk_header.chunk_hash(), &validator_signer); + let endorsement = ChunkEndorsementV1::new(chunk_header.chunk_hash(), &validator_signer); block.set_chunk_endorsements(vec![vec![Some(Box::new(endorsement.signature))]]); block.mut_header().get_mut().inner_rest.block_body_hash = block.compute_block_body_hash().unwrap();