Skip to content

Commit

Permalink
[stateless_validation] Stub code for handling chunk endorsement (#10405)
Browse files Browse the repository at this point in the history
This PR has the basic network stack stub for receiving and handling
chunk endorsements.
  • Loading branch information
Shreyan Gupta authored Jan 10, 2024
1 parent 6001359 commit 8b7891d
Show file tree
Hide file tree
Showing 14 changed files with 80 additions and 41 deletions.
14 changes: 13 additions & 1 deletion chain/client/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use near_network::types::{
use near_o11y::WithSpanContextExt;
use near_primitives::block::{Approval, Block, BlockHeader};
use near_primitives::challenge::Challenge;
use near_primitives::chunk_validation::ChunkStateWitness;
use near_primitives::chunk_validation::{ChunkEndorsement, ChunkStateWitness};
use near_primitives::errors::InvalidTxError;
use near_primitives::hash::CryptoHash;
use near_primitives::network::{AnnounceAccount, PeerId};
Expand Down Expand Up @@ -140,6 +140,10 @@ pub enum ProcessTxResponse {
#[rtype(result = "()")]
pub struct ChunkStateWitnessMessage(pub ChunkStateWitness);

#[derive(actix::Message, Debug)]
#[rtype(result = "()")]
pub struct ChunkEndorsementMessage(pub ChunkEndorsement);

pub struct Adapter {
/// Address of the client actor.
client_addr: actix::Addr<ClientActor>,
Expand Down Expand Up @@ -345,4 +349,12 @@ impl near_network::client::Client for Adapter {
Err(err) => tracing::error!("mailbox error: {err}"),
}
}

async fn chunk_endorsement(&self, endorsement: ChunkEndorsement) {
match self.client_addr.send(ChunkEndorsementMessage(endorsement).with_span_context()).await
{
Ok(()) => {}
Err(err) => tracing::error!("mailbox error: {err}"),
}
}
}
28 changes: 18 additions & 10 deletions chain/client/src/chunk_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ use near_network::types::{NetworkRequests, PeerManagerMessageRequest};
use near_primitives::challenge::PartialState;
use near_primitives::checked_feature;
use near_primitives::chunk_validation::{
ChunkEndorsement, ChunkEndorsementInner, ChunkEndorsementMessage, ChunkStateTransition,
ChunkStateWitness,
ChunkEndorsement, ChunkEndorsementInner, ChunkStateTransition, ChunkStateWitness,
};
use near_primitives::hash::{hash, CryptoHash};
use near_primitives::merkle::merklize;
Expand Down Expand Up @@ -106,15 +105,13 @@ impl ChunkValidator {
"Chunk validated successfully, sending endorsement",
);
let endorsement_to_sign = ChunkEndorsementInner::new(chunk_header.chunk_hash());
let endorsement = ChunkEndorsement {
account_id: signer.validator_id().clone(),
signature: signer.sign_chunk_endorsement(&endorsement_to_sign),
inner: endorsement_to_sign,
};
network_sender.send(PeerManagerMessageRequest::NetworkRequests(
NetworkRequests::ChunkEndorsement(ChunkEndorsementMessage {
endorsement: ChunkEndorsement {
account_id: signer.validator_id().clone(),
signature: signer.sign_chunk_endorsement(&endorsement_to_sign),
inner: endorsement_to_sign,
},
target: block_producer,
}),
NetworkRequests::ChunkEndorsement(block_producer, endorsement),
));
}
Err(err) => {
Expand Down Expand Up @@ -471,4 +468,15 @@ impl Client {
));
Ok(())
}

/// Function to process an incoming chunk endorsement from chunk validators.
pub fn process_chunk_endorsement(
&mut self,
_endorsement: ChunkEndorsement,
) -> Result<(), Error> {
// TODO(10265): Here if we are the current block producer, we would store the chunk endorsement
// for each chunk which would later be used during block production to check whether to include the
// chunk or not.
Ok(())
}
}
21 changes: 19 additions & 2 deletions chain/client/src/client_actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
//! https://github.com/near/nearcore/issues/7899
use crate::adapter::{
BlockApproval, BlockHeadersResponse, BlockResponse, ChunkStateWitnessMessage, ProcessTxRequest,
ProcessTxResponse, RecvChallenge, SetNetworkInfo, StateResponse,
BlockApproval, BlockHeadersResponse, BlockResponse, ChunkEndorsementMessage,
ChunkStateWitnessMessage, ProcessTxRequest, ProcessTxResponse, RecvChallenge, SetNetworkInfo,
StateResponse,
};
#[cfg(feature = "test_features")]
use crate::client::AdvProduceBlocksMode;
Expand Down Expand Up @@ -2007,6 +2008,22 @@ impl Handler<WithSpanContext<ChunkStateWitnessMessage>> for ClientActor {
}
}

impl Handler<WithSpanContext<ChunkEndorsementMessage>> for ClientActor {
type Result = ();

#[perf]
fn handle(
&mut self,
msg: WithSpanContext<ChunkEndorsementMessage>,
_: &mut Context<Self>,
) -> Self::Result {
let (_span, msg) = handler_debug_span!(target: "client", msg);
if let Err(err) = self.client.process_chunk_endorsement(msg.0) {
tracing::error!(target: "client", ?err, "Error processing chunk endorsement");
}
}
}

/// Returns random seed sampled from the current thread
pub fn random_seed_from_thread() -> RngSeed {
let mut rng_seed: RngSeed = [0; 32];
Expand Down
2 changes: 1 addition & 1 deletion chain/client/src/test_utils/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ pub fn setup_mock_all_validators(
NetworkRequests::ChunkStateWitness(_, _) => {
// TODO(#10265): Implement for integration tests.
},
NetworkRequests::ChunkEndorsement(_) => {
NetworkRequests::ChunkEndorsement(_, _) => {
// TODO(#10265): Implement for integration tests.
},
};
Expand Down
6 changes: 3 additions & 3 deletions chain/client/src/test_utils/test_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use near_o11y::testonly::TracingCapture;
use near_parameters::RuntimeConfig;
use near_primitives::action::delegate::{DelegateAction, NonDelegateAction, SignedDelegateAction};
use near_primitives::block::Block;
use near_primitives::chunk_validation::ChunkEndorsementMessage;
use near_primitives::chunk_validation::ChunkEndorsement;
use near_primitives::epoch_manager::RngSeed;
use near_primitives::errors::InvalidTxError;
use near_primitives::hash::CryptoHash;
Expand Down Expand Up @@ -286,7 +286,7 @@ impl TestEnv {
}
}

pub fn get_all_chunk_endorsements(&mut self) -> Vec<ChunkEndorsementMessage> {
pub fn get_all_chunk_endorsements(&mut self) -> Vec<ChunkEndorsement> {
let mut approvals = Vec::new();
for idx in 0..self.clients.len() {
let _span =
Expand All @@ -295,7 +295,7 @@ impl TestEnv {

self.network_adapters[idx].handle_filtered(|msg| {
if let PeerManagerMessageRequest::NetworkRequests(
NetworkRequests::ChunkEndorsement(endorsement),
NetworkRequests::ChunkEndorsement(_, endorsement),
) = msg
{
approvals.push(endorsement);
Expand Down
6 changes: 5 additions & 1 deletion chain/network/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::types::{NetworkInfo, ReasonForBan};

use near_primitives::block::{Approval, Block, BlockHeader};
use near_primitives::challenge::Challenge;
use near_primitives::chunk_validation::ChunkStateWitness;
use near_primitives::chunk_validation::{ChunkEndorsement, ChunkStateWitness};
use near_primitives::hash::CryptoHash;
use near_primitives::network::{AnnounceAccount, PeerId};
use near_primitives::transaction::SignedTransaction;
Expand Down Expand Up @@ -65,6 +65,8 @@ pub trait Client: Send + Sync + 'static {
) -> Result<Vec<AnnounceAccount>, ReasonForBan>;

async fn chunk_state_witness(&self, witness: ChunkStateWitness);

async fn chunk_endorsement(&self, endorsement: ChunkEndorsement);
}

/// Implementation of Client which doesn't do anything and never returns errors.
Expand Down Expand Up @@ -134,4 +136,6 @@ impl Client for Noop {
}

async fn chunk_state_witness(&self, _witness: ChunkStateWitness) {}

async fn chunk_endorsement(&self, _endorsement: ChunkEndorsement) {}
}
4 changes: 2 additions & 2 deletions chain/network/src/peer/peer_actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -992,8 +992,8 @@ impl PeerActor {
network_state.client.chunk_state_witness(witness).await;
None
}
RoutedMessageBody::ChunkEndorsement(_) => {
// TODO(#10265): Handle chunk approvals.
RoutedMessageBody::ChunkEndorsement(endorsement) => {
network_state.client.chunk_endorsement(endorsement).await;
None
}
body => {
Expand Down
6 changes: 3 additions & 3 deletions chain/network/src/peer_manager/peer_manager_actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -968,11 +968,11 @@ impl PeerManagerActor {
}
NetworkResponses::NoResponse
}
NetworkRequests::ChunkEndorsement(approval) => {
NetworkRequests::ChunkEndorsement(target, endorsement) => {
self.state.send_message_to_account(
&self.clock,
&approval.target,
RoutedMessageBody::ChunkEndorsement(approval.endorsement),
&target,
RoutedMessageBody::ChunkEndorsement(endorsement),
);
NetworkResponses::NoResponse
}
Expand Down
9 changes: 7 additions & 2 deletions chain/network/src/testonly/fake_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::types::{NetworkInfo, ReasonForBan, StateResponseInfoV2};
use near_async::messaging;
use near_primitives::block::{Approval, Block, BlockHeader};
use near_primitives::challenge::Challenge;
use near_primitives::chunk_validation::ChunkStateWitness;
use near_primitives::chunk_validation::{ChunkEndorsement, ChunkStateWitness};
use near_primitives::hash::CryptoHash;
use near_primitives::network::{AnnounceAccount, PeerId};
use near_primitives::sharding::{ChunkHash, PartialEncodedChunkPart};
Expand All @@ -19,12 +19,13 @@ use near_primitives::views::FinalExecutionOutcomeView;
pub enum Event {
AnnounceAccount(Vec<(AnnounceAccount, Option<EpochId>)>),
Block(Block),
BlockHeaders(Vec<BlockHeader>),
BlockApproval(Approval, PeerId),
BlockHeaders(Vec<BlockHeader>),
BlockHeadersRequest(Vec<CryptoHash>),
BlockRequest(CryptoHash),
Challenge(Challenge),
Chunk(Vec<PartialEncodedChunkPart>),
ChunkEndorsement(ChunkEndorsement),
ChunkRequest(ChunkHash),
ChunkStateWitness(ChunkStateWitness),
Transaction(SignedTransaction),
Expand Down Expand Up @@ -123,6 +124,10 @@ impl client::Client for Fake {
async fn chunk_state_witness(&self, witness: ChunkStateWitness) {
self.event_sink.push(Event::ChunkStateWitness(witness));
}

async fn chunk_endorsement(&self, endorsement: ChunkEndorsement) {
self.event_sink.push(Event::ChunkEndorsement(endorsement));
}
}

impl messaging::CanSend<ShardsManagerRequestFromNetwork> for Fake {
Expand Down
8 changes: 3 additions & 5 deletions chain/network/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use near_async::time;
use near_crypto::PublicKey;
use near_primitives::block::{ApprovalMessage, Block, GenesisId};
use near_primitives::challenge::Challenge;
use near_primitives::chunk_validation::{ChunkEndorsementMessage, ChunkStateWitness};
use near_primitives::chunk_validation::{ChunkEndorsement, ChunkStateWitness};
use near_primitives::hash::CryptoHash;
use near_primitives::network::{AnnounceAccount, PeerId};
use near_primitives::sharding::PartialEncodedChunkWithArcReceipts;
Expand Down Expand Up @@ -251,7 +251,6 @@ pub enum NetworkRequests {
},
/// Forwarding a chunk part to a validator tracking the shard
PartialEncodedChunkForward { account_id: AccountId, forward: PartialEncodedChunkForwardMsg },

/// Valid transaction but since we are not validators we send this transaction to current validators.
ForwardTx(AccountId, SignedTransaction),
/// Query transaction status
Expand All @@ -260,9 +259,8 @@ pub enum NetworkRequests {
Challenge(Challenge),
/// A chunk's state witness.
ChunkStateWitness(Vec<AccountId>, ChunkStateWitness),
/// Message for a chunk endorsement, sent by a chunk validator to
/// the block producer.
ChunkEndorsement(ChunkEndorsementMessage),
/// Message for a chunk endorsement, sent by a chunk validator to the block producer.
ChunkEndorsement(AccountId, ChunkEndorsement),
}

/// Combines peer address info, chain.
Expand Down
8 changes: 0 additions & 8 deletions core/primitives/src/chunk_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,6 @@ impl ChunkEndorsementInner {
}
}

/// Message intended for the network layer to send a chunk endorsement.
/// It just includes an additional target account ID to send it to.
#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
pub struct ChunkEndorsementMessage {
pub endorsement: ChunkEndorsement,
pub target: AccountId,
}

/// Stored on disk for each chunk, including missing chunks, in order to
/// produce a chunk state witness when needed.
#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ impl ChunkForwardingOptimizationTestData {
);
}
NetworkRequests::ChunkStateWitness(_, _) => {}
NetworkRequests::ChunkEndorsement(_) => {}
NetworkRequests::ChunkEndorsement(_, _) => {}
_ => {
panic!("Unexpected network request: {:?}", requests);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,10 @@ impl AdversarialBehaviorTestData {
NetworkRequests::Challenge(_) => {
// challenges not enabled.
}
NetworkRequests::ChunkEndorsement(_) => {
NetworkRequests::ChunkStateWitness(_, _) => {
// TODO(#10265).
}
NetworkRequests::ChunkStateWitness(_, _) => {
NetworkRequests::ChunkEndorsement(_, _) => {
// TODO(#10265).
}
_ => {
Expand Down
3 changes: 3 additions & 0 deletions tools/chainsync-loadtest/src/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use near_network::types::{
};
use near_primitives::block::{Approval, Block, BlockHeader};
use near_primitives::challenge::Challenge;
use near_primitives::chunk_validation::ChunkEndorsement;
use near_primitives::chunk_validation::ChunkStateWitness;
use near_primitives::hash::CryptoHash;
use near_primitives::network::{AnnounceAccount, PeerId};
Expand Down Expand Up @@ -305,4 +306,6 @@ impl near_network::client::Client for Network {
}

async fn chunk_state_witness(&self, _witness: ChunkStateWitness) {}

async fn chunk_endorsement(&self, _endorsement: ChunkEndorsement) {}
}

0 comments on commit 8b7891d

Please sign in to comment.